Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[perl #38790] readdir() only returns one result when used with Fatal.pm

0 views
Skip to first unread message

Tom Hukins

unread,
Mar 23, 2006, 7:04:03 AM3/23/06
to bugs-bi...@rt.perl.org
# New Ticket Created by Tom Hukins
# Please include the string: [perl #38790]
# in the subject line of all future correspondence about this issue.
# <URL: https://rt.perl.org/rt3/Ticket/Display.html?id=38790 >


This is a bug report for perl from t...@eborcom.com,
generated with the help of perlbug 1.35 running under perl v5.8.7.


-----------------------------------------------------------------
[Please enter your report here]

Fatal.pm and readdir() do not play well together. Run the following
script in a directory containing several files. It only prints out '.'.
Then comment out the 'use Fatal' line and run the script again. It now
prints out all the files in the directory.

#!/usr/bin/perl

use strict;
use warnings;

use Fatal qw(readdir);

my $start_dir = '.';
opendir(my $dir, $start_dir);
my @subdir = readdir $dir;
closedir $dir;
print "@subdir\n";


[Please do not change anything below this line]
-----------------------------------------------------------------
---
Flags:
category=library
severity=medium
---
Site configuration information for perl v5.8.7:

Configured by tomh at Wed Aug 10 15:04:17 UTC 2005.

Summary of my perl5 (revision 5 version 8 subversion 7) configuration:
Platform:
osname=freebsd, osvers=5.4-release, archname=i386-freebsd-64int
uname='freebsd tomvmware.spirainternal.co.uk 5.4-release freebsd 5.4-release #0: sun may 8 10:21:06 utc 2005 ro...@harlow.cse.buffalo.edu:usrobjusrsrcsysgeneric i386 '
config_args='-sde -Dprefix=/usr/local -Darchlib=/usr/local/lib/perl5/5.8.7/mach -Dprivlib=/usr/local/lib/perl5/5.8.7 -Dman3dir=/usr/local/lib/perl5/5.8.7/perl/man/man3 -Dman1dir=/usr/local/man/man1 -Dsitearch=/usr/local/lib/perl5/site_perl/5.8.7/mach -Dsitelib=/usr/local/lib/perl5/site_perl/5.8.7 -Dscriptdir=/usr/local/bin -Dsiteman3dir=/usr/local/lib/perl5/5.8.7/man/man3 -Dsiteman1dir=/usr/local/man/man1 -Ui_malloc -Ui_iconv -Uinstallusrbinperl -Dcc=cc -Duseshrplib -Dccflags=-DAPPLLIB_EXP="/usr/local/lib/perl5/5.8.7/BSDPAN" -Doptimize=-O -pipe -march=pentium4 -Ud_dosuid -Ui_gdbm -Dusethreads=n -Dusemymalloc=y -Duse64bitint'
hint=recommended, useposix=true, d_sigaction=define
usethreads=undef use5005threads=undef useithreads=undef usemultiplicity=undef
useperlio=define d_sfio=undef uselargefiles=define usesocks=undef
use64bitint=define use64bitall=undef uselongdouble=undef
usemymalloc=y, bincompat5005=undef
Compiler:
cc='cc', ccflags ='-DAPPLLIB_EXP="/usr/local/lib/perl5/5.8.7/BSDPAN" -DHAS_FPSETMASK -DHAS_FLOATINGPOINT_H -fno-strict-aliasing -pipe -I/usr/local/include',
optimize='-O -pipe -march=pentium4',
cppflags='-DAPPLLIB_EXP="/usr/local/lib/perl5/5.8.7/BSDPAN" -DHAS_FPSETMASK -DHAS_FLOATINGPOINT_H -fno-strict-aliasing -pipe -I/usr/local/include'
ccversion='', gccversion='3.4.2 [FreeBSD] 20040728', gccosandvers=''
intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=12345678
d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12
ivtype='long long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
alignbytes=4, prototype=define
Linker and Libraries:
ld='cc', ldflags ='-pthread -Wl,-E -L/usr/local/lib'
libpth=/usr/lib /usr/local/lib
libs=-lm -lcrypt -lutil
perllibs=-lm -lcrypt -lutil
libc=, so=so, useshrplib=true, libperl=libperl.so
gnulibc_version=''
Dynamic Linking:
dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags=' -Wl,-R/usr/local/lib/perl5/5.8.7/mach/CORE'
cccdlflags='-DPIC -fPIC', lddlflags='-shared -L/usr/local/lib'

Locally applied patches:
defined-or

---
@INC for perl v5.8.7:
/usr/local/lib/perl5/site_perl/5.8.7
/usr/local/lib/perl5/site_perl/5.8.7/mach
/usr/local/lib/perl5/site_perl
/usr/local/lib/perl5/5.8.7/BSDPAN
/usr/local/lib/perl5/5.8.7/mach
/usr/local/lib/perl5/5.8.7
.

---
Environment for perl v5.8.7:
HOME=/home/tomh
LANG (unset)
LANGUAGE (unset)
LD_LIBRARY_PATH (unset)
LOGDIR (unset)
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/games:/usr/local/sbin:/usr/local/bin:/usr/X11R6/bin:/home/tomh/bin
PERL_BADLANG (unset)
SHELL=/usr/local/bin/zsh

Rafael Garcia-Suarez

unread,
Mar 23, 2006, 8:03:57 AM3/23/06
to perl5-...@perl.org
Tom Hukins (via RT) wrote:
> Fatal.pm and readdir() do not play well together. Run the following
> script in a directory containing several files. It only prints out '.'.
> Then comment out the 'use Fatal' line and run the script again. It now
> prints out all the files in the directory.
>
> #!/usr/bin/perl
>
> use strict;
> use warnings;
>
> use Fatal qw(readdir);
>
> my $start_dir = '.';
> opendir(my $dir, $start_dir);
> my @subdir = readdir $dir;
> closedir $dir;
> print "@subdir\n";

Fatal will replace readdir() by this function :

sub (*) {
local($", $!) = (', ', 0);
CORE::readdir($_[0]) || croak "Can't readdir(@_): $!";
}

As you see, this construct forces readdir to be called in scalar
context; which is why it returns only one element, as documented
in perlfunc.

We could add a wantarray() before that, but that would alter the proper
behaviour of other weird code like this :

use Fatal qw(open);
my @useless_array = open my $fh, "non-existent-file";

Other ideas ?

--
No matter what scheme is chosen, most of the world is unhappy.
-- Jeff Johnson in rpm-devel

Yitzchak Scott-Thoennes

unread,
Mar 23, 2006, 8:30:46 AM3/23/06
to Rafael Garcia-Suarez, perl5-...@perl.org

*Is* there any way to detect a failed list-context readdir()? If not,
Fatal should continue to do what it is doing and the limitation should
be documented.

Rafael Garcia-Suarez

unread,
Mar 23, 2006, 9:45:18 AM3/23/06
to Yitzchak Scott-Thoennes, perl5-...@perl.org
Yitzchak Scott-Thoennes wrote:
>
> *Is* there any way to detect a failed list-context readdir()?

Due to the iterative nature of readdir(), I doubt Fatal makes sense on
it, from a language point of view. But strictly speaking, readdir()
fails when there are no more entries to read, that is, by returning
undef in scalar context, and an empty list in list context.

> If not,
> Fatal should continue to do what it is doing and the limitation should
> be documented.

That would be probably the best solution, but I wonder whether other
builtins could cause the same kind of problems. A glance through the
keyword list doesn't give other ideas. (Maybe select(), which returns -1
on error.) There is also a minor inconsistency on some error values :
some return 0 on error, some return undef (because 0 could be returned
in case of success -- e.g. read()). So, short of harcoding all
exceptions, there is no good fix.

Joshua ben Jore

unread,
Mar 23, 2006, 12:09:47 PM3/23/06
to Rafael Garcia-Suarez, Yitzchak Scott-Thoennes, perl5-...@perl.org

So hardcode the exceptions. They're well established and limited.
Heck, for readdir(), if it returned an empty list/undef, why isn't $!
being examined to decide failure? It isn't that failure is
undetectable, it just isn't a case of looking at the return value
because any of empty/false/undef/-1/0 are possible as non-error
returns.

It could be considered the responsibility of a core module like Fatal
to handle all the various exceptional return values. I sure do. I also
see no reason why Fatal can't do the right thing. So why is it that
Fatal has to just document this as a limitation? It's possible for
Fatal to handle list context readdir, right? If so, it should.

Josh

Rafael Garcia-Suarez

unread,
Mar 23, 2006, 12:25:41 PM3/23/06
to Joshua ben Jore, Yitzchak Scott-Thoennes, perl5-...@perl.org
Joshua ben Jore wrote:
>
> So hardcode the exceptions. They're well established and limited.
> Heck, for readdir(), if it returned an empty list/undef, why isn't $!
> being examined to decide failure? It isn't that failure is
> undetectable, it just isn't a case of looking at the return value
> because any of empty/false/undef/-1/0 are possible as non-error
> returns.

Not sure, I think all directories have always at least one entries.
At least on Unixes.

> It could be considered the responsibility of a core module like Fatal
> to handle all the various exceptional return values. I sure do. I also
> see no reason why Fatal can't do the right thing. So why is it that
> Fatal has to just document this as a limitation? It's possible for
> Fatal to handle list context readdir, right? If so, it should.

Yes, seems reasonable. and patches speak louder than words :)

Joshua ben Jore

unread,
Mar 23, 2006, 1:43:02 PM3/23/06
to Rafael Garcia-Suarez, Yitzchak Scott-Thoennes, perl5-...@perl.org
On 3/23/06, Rafael Garcia-Suarez <rgarci...@mandriva.com> wrote:
> Joshua ben Jore wrote:
> > Fatal has to just document this as a limitation? It's possible for
> > Fatal to handle list context readdir, right? If so, it should.
>
> Yes, seems reasonable. and patches speak louder than words :)

I was just considering which evening I wanted to give up for this. I
want to get the modules that are in perl's core lint-safe. I suppose
I'd prefer this patch first. :-/ I do have some tweaks to lint
outstanding and will send them on when I've got the tests written.

Josh

John E. Malmberg

unread,
Mar 23, 2006, 11:03:09 PM3/23/06
to Rafael Garcia-Suarez, Joshua ben Jore, Yitzchak Scott-Thoennes, perl5-...@perl.org
Rafael Garcia-Suarez wrote:
> Joshua ben Jore wrote:
>
>>So hardcode the exceptions. They're well established and limited.
>>Heck, for readdir(), if it returned an empty list/undef, why isn't $!
>>being examined to decide failure? It isn't that failure is
>>undetectable, it just isn't a case of looking at the return value
>>because any of empty/false/undef/-1/0 are possible as non-error
>>returns.
>
> Not sure, I think all directories have always at least one entries.
> At least on Unixes.

OpenVMS directories can be empty and frequently are.

-John
wb8...@qsl.net
Personal Opinion Only

0 new messages