Perl / perl5

🐪 The Perl programming language
https://dev.perl.org/perl5/
Other
1.94k stars 553 forks source link

closing STDIN causes warning when opening unrelated file #12757

Open p5pRT opened 11 years ago

p5pRT commented 11 years ago

Migrated from rt.perl.org#116659 (status was 'open')

Searchable as RT116659$

p5pRT commented 11 years ago

From @jimav

This is a bug report for perl from james_avera@​yahoo.com\, generated with the help of perlbug 1.39 running under perl 5.14.2.


Not saying this is a bug\, but it seems wrong to not permit STDIN to be closed​:

  perl -we 'close STDIN; open my $fh\,">/dev/null";'   Filehandle STDIN reopened as $fh only for output at -e line 1.

It sounds like Perl implicitly re-opens STDIN when fd 0 gets re-used for something else. It might be better to not complain about this but die later if the handle STDIN is ever actually opened and the fd does not end up being zero.



Flags​:   category=core   severity=none


Site configuration information for perl 5.14.2​:

Configured by Debian Project at Tue Nov 27 00​:34​:23 UTC 2012.

Summary of my perl5 (revision 5 version 14 subversion 2) configuration​:  
  Platform​:   osname=linux\, osvers=2.6.42-32-generic\, archname=x86_64-linux-gnu-thread-multi   uname='linux allspice 2.6.42-32-generic #51-ubuntu smp wed sep 26 21​:33​:09 utc 2012 x86_64 x86_64 x86_64 gnulinux '   config_args='-Dusethreads -Duselargefiles -Dccflags=-DDEBIAN -Dcccdlflags=-fPIC -Darchname=x86_64-linux-gnu -Dprefix=/usr -Dprivlib=/usr/share/perl/5.14 -Darchlib=/usr/lib/perl/5.14 -Dvendorprefix=/usr -Dvendorlib=/usr/share/perl5 -Dvendorarch=/usr/lib/perl5 -Dsiteprefix=/usr/local -Dsitelib=/usr/local/share/perl/5.14.2 -Dsitearch=/usr/local/lib/perl/5.14.2 -Dman1dir=/usr/share/man/man1 -Dman3dir=/usr/share/man/man3 -Dsiteman1dir=/usr/local/man/man1 -Dsiteman3dir=/usr/local/man/man3 -Duse64bitint -Dman1ext=1 -Dman3ext=3perl -Dpager=/usr/bin/sensible-pager -Uafs -Ud_csh -Ud_ualarm -Uusesfio -Uusenm -Ui_libutil -DDEBUGGING=-g -Doptimize=-O2 -Duseshrplib -Dlibperl=libperl.so.5.14.2 -des'   hint=recommended\, useposix=true\, d_sigaction=define   useithreads=define\, usemultiplicity=define   useperlio=define\, d_sfio=undef\, uselargefiles=define\, usesocks=undef   use64bitint=define\, use64bitall=define\, uselongdouble=undef   usemymalloc=n\, bincompat5005=undef   Compiler​:   cc='cc'\, ccflags ='-D_REENTRANT -D_GNU_SOURCE -DDEBIAN -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64'\,   optimize='-O2 -g'\,   cppflags='-D_REENTRANT -D_GNU_SOURCE -DDEBIAN -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include'   ccversion=''\, gccversion='4.6.3'\, gccosandvers=''   intsize=4\, longsize=8\, ptrsize=8\, doublesize=8\, byteorder=12345678   d_longlong=define\, longlongsize=8\, d_longdbl=define\, longdblsize=16   ivtype='long'\, ivsize=8\, nvtype='double'\, nvsize=8\, Off_t='off_t'\, lseeksize=8   alignbytes=8\, prototype=define   Linker and Libraries​:   ld='cc'\, ldflags =' -fstack-protector -L/usr/local/lib'   libpth=/usr/local/lib /lib/x86_64-linux-gnu /lib/../lib /usr/lib/x86_64-linux-gnu /usr/lib/../lib /lib /usr/lib   libs=-lgdbm -lgdbm_compat -ldb -ldl -lm -lpthread -lc -lcrypt   perllibs=-ldl -lm -lpthread -lc -lcrypt   libc=\, so=so\, useshrplib=true\, libperl=libperl.so.5.14.2   gnulibc_version='2.15'   Dynamic Linking​:   dlsrc=dl_dlopen.xs\, dlext=so\, d_dlsymun=undef\, ccdlflags='-Wl\,-E'   cccdlflags='-fPIC'\, lddlflags='-shared -O2 -g -L/usr/local/lib -fstack-protector'

Locally applied patches​:  


@​INC for perl 5.14.2​:   /home/jima/lib/perl   /home/jima/perl5/lib/perl5/x86_64-linux-gnu-thread-multi   /home/jima/perl5/lib/perl5/x86_64-linux-gnu-thread-multi   /home/jima/perl5/lib/perl5   /etc/perl   /usr/local/lib/perl/5.14.2   /usr/local/share/perl/5.14.2   /usr/lib/perl5   /usr/share/perl5   /usr/lib/perl/5.14   /usr/share/perl/5.14   /usr/local/lib/site_perl   .


Environment for perl 5.14.2​:   HOME=/home/jima   LANG=en_US.UTF-8   LANGUAGE=   LD_LIBRARY_PATH=/home/jima/local/lib   LOGDIR (unset)   PATH=/home/jima/perl5/bin​:/home/jima/bin​:/home/jima/local/bin​:/home/jima/jima_tools/bin​:/usr/bin​:/bin​:/usr/sbin​:/sbin​:/usr/bin/X11​:/usr/local/bin​:/usr/local/sbin​:/usr/games​:.   PERL5LIB=/home/jima/lib/perl​:/home/jima/perl5/lib/perl5/x86_64-linux-gnu-thread-multi​:/home/jima/perl5/lib/perl5   PERL_BADLANG (unset)   PERL_LOCAL_LIB_ROOT=/home/jima/perl5   PERL_MB_OPT=--install_base /home/jima/perl5   PERL_MM_OPT=INSTALL_BASE=/home/jima/perl5   SHELL=/bin/bash

p5pRT commented 11 years ago

From @Leont

On Wed\, Feb 6\, 2013 at 2​:33 AM\, Jim Avera \perlbug\-followup@​perl\.org wrote​:

Not saying this is a bug\, but it seems wrong to not permit STDIN to be closed​:

perl -we 'close STDIN; open my $fh\,">/dev/null";' Filehandle STDIN reopened as $fh only for output at -e line 1.

It sounds like Perl implicitly re-opens STDIN when fd 0 gets re-used for something else. It might be better to not complain about this but die later if the handle STDIN is ever actually opened and the fd does not end up being zero.

You just closed STDIN(fd=0) The underlying system allocates the lowest fd available (at this point always fd=0) This leads to a nonsensible situation\, so perl gives a warning.

Why would you want to do this in the first place?

Leon

p5pRT commented 11 years ago

The RT System itself - Status changed from 'new' to 'open'

p5pRT commented 11 years ago

From @xdg

On Tue\, Feb 5\, 2013 at 9​:07 PM\, Leon Timmermans \fawaka@​gmail\.com wrote​:

Why would you want to do this in the first place?

It's slightly worse than that. If you close STDIN and then your program requires a module\, the handle for loading it will wind up on fd 0\, too.

Capture​::Tiny goes through some hoops to avoid that\, but it would be nice if the core could find a way to stay off fd 0 (assuming a sufficiently portable way to do so exists).

David

-- David Golden \xdg@​xdg\.me Take back your inbox! → http​://www.bunchmail.com/ Twitter/IRC​: @​xdg

p5pRT commented 11 years ago

From @arc

David Golden \xdg@​xdg\.me wrote​:

If you close STDIN and then your program requires a module\, the handle for loading it will wind up on fd 0\, too.

Capture​::Tiny goes through some hoops to avoid that\, but it would be nice if the core could find a way to stay off fd 0 (assuming a sufficiently portable way to do so exists).

For Unixish systems\, I think the approach would be to look at the fd returned by open() (or pipe()\, or socket()\, or what-have-you)\, and while it's one of 0\,1\,2\, dup() it; then close() the original fd\, and any others that were in the bad range. (That's portable back to Seventh Edition\, and probably earlier.)

I don't know what hoops Capture​::Tiny jumps through in this case\, but AFAICT\, that logic should work in Perl space just as well as in C space.

I'm afraid I have no idea what that would do on Win32 or VMS\, or if the question's even meaningful there. Anyone else?

-- Aaron Crane ** http​://aaroncrane.co.uk/

p5pRT commented 11 years ago

From @Leont

On Wed\, Feb 6\, 2013 at 6​:58 PM\, David Golden \xdg@​xdg\.me wrote​:

Capture​::Tiny goes through some hoops to avoid that\, but it would be nice if the core could find a way to stay off fd 0 (assuming a sufficiently portable way to do so exists).

Judging from googleing around dup/dup2 is portable among Unix\, Windows and VMS. It should be possible.

Leon

p5pRT commented 11 years ago

From @iabyn

On Tue\, Feb 05\, 2013 at 05​:33​:02PM -0800\, Jim Avera wrote​:

Not saying this is a bug\, but it seems wrong to not permit STDIN to be closed​:

perl -we 'close STDIN; open my $fh\,">/dev/null";' Filehandle STDIN reopened as $fh only for output at -e line 1.

It sounds like Perl implicitly re-opens STDIN when fd 0 gets re-used for something else. It might be better to not complain about this but die later if the handle STDIN is ever actually opened and the fd does not end up being zero.

Note that the warning is a bit misleading. It's really trying to say that $fh has been opened with the file descriptor normally associated with STDIN (i.e. fd 0)\, rather than saying that the perl filehandle STDIN has been re-opened. The perl handle STDIN is still closed (for both reading and writing).

-- Indomitable in retreat\, invincible in advance\, insufferable in victory   -- Churchill on Montgomery

p5pRT commented 11 years ago

From @xdg

On Wed\, Feb 6\, 2013 at 2​:08 PM\, Aaron Crane \arc@​cpan\.org wrote​:

I don't know what hoops Capture​::Tiny jumps through in this case\, but AFAICT\, that logic should work in Perl space just as well as in C space.

If I recall\, if it sees STDIN closed\, it opens it to File​::Spec->devnull for the duration of the capture (while monkeying around extensively with handles) and then closes it again afterwards.

-- David Golden \xdg@​xdg\.me Take back your inbox! → http​://www.bunchmail.com/ Twitter/IRC​: @​xdg

p5pRT commented 11 years ago

From Eirik-Berg.Hanssen@allverden.no

On Thu\, Feb 7\, 2013 at 2​:56 PM\, David Golden \xdg@​xdg\.me wrote​:

On Wed\, Feb 6\, 2013 at 2​:08 PM\, Aaron Crane \arc@​cpan\.org wrote​:

I don't know what hoops Capture​::Tiny jumps through in this case\, but AFAICT\, that logic should work in Perl space just as well as in C space.

If I recall\, if it sees STDIN closed\, it opens it to File​::Spec->devnull for the duration of the capture (while monkeying around extensively with handles) and then closes it again afterwards.

  I'd rather perl did not jump through that particular hoop without being asked ...

  Beyond performance and wasted file handles\, I'd say something about not trying to keep people from doing stupid things\, as that would also keep them from doing clever things.

  But why is there even a warning here? I read perldiag\, but found no rationale.

  (What might break? Do some system prevent output on file handle 0? Could a child process inherit this fd0\, and blow up since it is opened\, but not for reading?)

  If there really is a reason\, it'd be nice if perldiag gave it. :)

Eirik

p5pRT commented 11 years ago

From @xdg

On Thu\, Feb 7\, 2013 at 9​:47 AM\, Eirik Berg Hanssen \Eirik\-Berg\.Hanssen@​allverden\.no wrote​:

(What might break? Do some system prevent output on file handle 0? Could a child process inherit this fd0\, and blow up since it is opened\, but not for reading?)

* You close STDIN (for whatever reason) * You require a module that has a __DATA__ section * You launch a process... and it's STDIN is in the __DATA__ section.

Example​:

# Foo.pm package Foo; 1; __DATA__ Just another perl hacker

###########

# run.pl use v5.10; use strict; use warnings; use lib '.';

close STDIN; require Foo; say `/bin/cat`;

###########

$ perl run.pl Just another perl hacker

-- David Golden \xdg@​xdg\.me Take back your inbox! → http​://www.bunchmail.com/ Twitter/IRC​: @​xdg

p5pRT commented 11 years ago

From Eirik-Berg.Hanssen@allverden.no

On Thu\, Feb 7\, 2013 at 8​:54 PM\, David Golden \xdg@​xdg\.me wrote​:

On Thu\, Feb 7\, 2013 at 9​:47 AM\, Eirik Berg Hanssen \Eirik\-Berg\.Hanssen@​allverden\.no wrote​:

(What might break? Do some system prevent output on file handle 0? Could a child process inherit this fd0\, and blow up since it is opened\, but not for reading?)

* You close STDIN (for whatever reason) * You require a module that has a __DATA__ section * You launch a process... and it's STDIN is in the __DATA__ section.

Example​:

# Foo.pm package Foo; 1; __DATA__ Just another perl hacker

###########

# run.pl use v5.10; use strict; use warnings; use lib '.';

close STDIN; require Foo; say `/bin/cat`;

###########

$ perl run.pl Just another perl hacker

  That seems like a perfectly good answer – to a different question. ;-)

  Thanks\, but you're not reopening fd0 for writing\, and so don't even get the warning.

  What you have done (by way of require) is open fd0 for reading. Valid gotcha\, but not relevant to this warning.

  If anything\, this would suggest a warning when reopening fd0 for reading. Maybe there should be ... maybe at least require should just not do it ... or maybe this is another case of not keeping people from doing clever things. ;-)

  On my current system\, I don't get a warning when I'm reopening fd0 for reading. Why do I get one when reopening fd0 for writing?

  (And vice-versa for fd1 and fd2\, of course.)

Eirik

p5pRT commented 11 years ago

From @xdg

On Thu\, Feb 7\, 2013 at 3​:32 PM\, Eirik Berg Hanssen \Eirik\-Berg\.Hanssen@​allverden\.no wrote​:

That seems like a perfectly good answer – to a different question. ;-)

It was the answer to why we should stay of fd 0 and avoid the problem.

In answer to your question\, probably because having a write-only handle on a descriptor that programs expect to read from makes them crash​:

# run2.pl use v5.10; use strict; use warnings; use lib '.';

close STDIN; open my $fh\, ">"\, "foo.xt"; say "opened on fd " . fileno $fh; say `/bin/cat`;

###

$ perl run2.pl Filehandle STDIN reopened as $fh only for output at run2.pl line 8. opened on fd 0 cat​: stdin​: Bad file descriptor

-- David Golden \xdg@​xdg\.me Take back your inbox! → http​://www.bunchmail.com/ Twitter/IRC​: @​xdg

p5pRT commented 11 years ago

From Eirik-Berg.Hanssen@allverden.no

On Thu\, Feb 7\, 2013 at 9​:54 PM\, David Golden \xdg@​xdg\.me wrote​:

On Thu\, Feb 7\, 2013 at 3​:32 PM\, Eirik Berg Hanssen \Eirik\-Berg\.Hanssen@​allverden\.no wrote​:

That seems like a perfectly good answer – to a different question. ;-)

It was the answer to why we should stay of fd 0 and avoid the problem.

  Mhm. To bad it's not easily controllable.

In answer to your question\, probably because having a write-only

handle on a descriptor that programs expect to read from makes them crash​:

  But that's not related to the reopening. A closed STDIN will also have the program crashing​:

eirik@​bluebird[22​:08​:26]~$ perl -wE 'close STDIN; system "/bin/cat"; say $?;' /bin/cat​: -​: Bad file descriptor /bin/cat​: closing standard input​: Bad file descriptor 256 eirik@​bluebird[22​:08​:34]~$ perl -wE 'close STDIN; open my $fh\, ">"\, "test"; system "/bin/cat"; say $?;' Filehandle STDIN reopened as $fh only for output at -e line 1. /bin/cat​: -​: Bad file descriptor 256 eirik@​bluebird[22​:08​:36]~$

  Okay\, those are slightly different chrashes (for cat; I've tried a few others\, but got no difference)\, but I don't see how that difference has only one of them meriting a warning.

  (Perhaps there are other instances where this difference makes a significant difference?)

  If both should warn\, the trigger should be executing a process with no fd0 opened for reading.

  But currently\, only one of them warns ... and I still cannot say I see a reason for it.

Eirik

p5pRT commented 11 years ago

From @xdg

On Thu\, Feb 7\, 2013 at 4​:22 PM\, Eirik Berg Hanssen \Eirik\-Berg\.Hanssen@​allverden\.no wrote​:

If both should warn\, the trigger should be executing a process with no fd0 opened for reading.

But currently\, only one of them warns ... and I still cannot say I see a reason for it.

So you're volunteering to write a patch?

-- David Golden \xdg@​xdg\.me Take back your inbox! → http​://www.bunchmail.com/ Twitter/IRC​: @​xdg

p5pRT commented 11 years ago

From Eirik-Berg.Hanssen@allverden.no

On Thu\, Feb 7\, 2013 at 10​:36 PM\, David Golden \xdg@​xdg\.me wrote​:

On Thu\, Feb 7\, 2013 at 4​:22 PM\, Eirik Berg Hanssen \Eirik\-Berg\.Hanssen@​allverden\.no wrote​:

If both should warn\, the trigger should be executing a process with no fd0 opened for reading.

But currently\, only one of them warns ... and I still cannot say I see a reason for it.

So you're volunteering to write a patch?

  Contingent on my eventually seeing a reason for this warning\, I might volunteer to patch perldiag.pod.

  If on the other hand you want both to warn\, that's too deep into C for me – you're better off submitting a feature request by the ordinary channels.

Eirik