Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

closing STDIN causes warning when opening unrelated file #12757

Open
p5pRT opened this issue Feb 6, 2013 · 15 comments
Open

closing STDIN causes warning when opening unrelated file #12757

p5pRT opened this issue Feb 6, 2013 · 15 comments

Comments

@p5pRT
Copy link

p5pRT commented Feb 6, 2013

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

Searchable as RT116659$

@p5pRT
Copy link
Author

p5pRT commented Feb 6, 2013

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
Copy link
Author

p5pRT commented Feb 6, 2013

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
Copy link
Author

p5pRT commented Feb 6, 2013

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

@p5pRT
Copy link
Author

p5pRT commented Feb 6, 2013

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
Copy link
Author

p5pRT commented Feb 6, 2013

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
Copy link
Author

p5pRT commented Feb 6, 2013

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
Copy link
Author

p5pRT commented Feb 7, 2013

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
Copy link
Author

p5pRT commented Feb 7, 2013

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
Copy link
Author

p5pRT commented Feb 7, 2013

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
Copy link
Author

p5pRT commented Feb 7, 2013

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
Copy link
Author

p5pRT commented Feb 7, 2013

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
Copy link
Author

p5pRT commented Feb 7, 2013

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
Copy link
Author

p5pRT commented Feb 7, 2013

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
Copy link
Author

p5pRT commented Feb 7, 2013

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
Copy link
Author

p5pRT commented Feb 8, 2013

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants