Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

perl bug when STDIN, STDOUT and STDERR get closed?

Tags:

perl

When writing a daemon, I want to close STDIN, STDOUT and STDERR for "good daemon behavior". But I got surprised. Subsequent opening of files require the same properties as the old STDIN, STDOUT and STDERR (because their fileno-s got re-opened?)

Here is warn.pl:

use warnings;

my $nrWarnings = 0;
$SIG{__WARN__} = sub {
    no warnings;
    $nrWarnings++;
    open my $log, '>>', '/tmp/log.txt'
        or die;
    printf $log "%d: %s", $nrWarnings, @_;
    close $log;
};

close STDOUT;
close STDERR;
close STDIN;

open my $o, '>', '/tmp/foobar.txt'
    or die;
open my $i, '<', '/etc/passwd'
    or die;
open my $i2, '<', '/etc/passwd'
    or die;
open my $i3, '<', '/etc/passwd'
    or die;

exit $nrWarnings;

And here I run it:

> rm -f /tmp/log.txt ; perl warn.pl; echo $? ; cat /tmp/log.txt 
3
1: Filehandle STDIN reopened as $o only for output at warn.pl line 20.
2: Filehandle STDOUT reopened as $i only for input at warn.pl line 22.
3: Filehandle STDERR reopened as $i2 only for input at warn.pl line 24.

I was expecting no warnings and $? == 0. Where is the bug? In my code or in perl?

This may appear similar to How can I reinitialize Perl's STDIN/STDOUT/STDERR?, but there the accepted solution was to close STDIN, STDOUT and STDERR like I do.

like image 378
Peter V. Mørch Avatar asked Dec 27 '22 05:12

Peter V. Mørch


2 Answers

Those are warnings, not errors. I suppose they exist because if your program subsequently forked and execed a different program, that program would be mightily confused that its standard input stream is opened for output and its standard output and error streams are opened for input.

It's perfectly legitimate to suppress warnings when you're sure you know what you're doing. In this case, you'd just add no warnings 'io'; prior to your opens.

like image 120
Sean Avatar answered Jan 09 '23 18:01

Sean


Now, right after hitting submit, I think of looking in perldoc perldiag and the warning text is listed there. That leads me to Perl bug #23838 which basically states: "Well, don't close those handles, re-open them to '/dev/null' instead".

And the bug is marked as resolved after that.

I disagree that re-opening to '/dev/null' is the correct way (tm), but now we venture into opinion, which is off-topic for stackoverflow, so I'll mark this as answered.

Sorry for the noise.

like image 29
Peter V. Mørch Avatar answered Jan 09 '23 18:01

Peter V. Mørch