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
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
*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.
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.
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
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 :)
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
OpenVMS directories can be empty and frequently are.
-John
wb8...@qsl.net
Personal Opinion Only