On Jun 1, 2012, at 4:53 AM, Jeff King wrote:
On Thu, May 31, 2012 at 08:39:42AM -0500, Travis P wrote:
Here's what I learned this morning: it appears to work when I don't
close STDIN.
#close $_ for *STDIN, *STDOUT, *STDERR; # What I was doing. Fails.
close $_ for *STDOUT, *STDERR; # Tried this, it works.
*STDOUT = $log_fh;
*STDERR = $log_fh;
Yeah, don't do that. This can cause subtle bugs in subprocesses. For
example:
1. You don't have a descriptor 0, because it is closed.
2. Some part of the program opens a new descriptor (e.g., to read a
file, making a pipe, etc). This becomes descriptor 0, because it
is
the lowest unused descriptor.
3. The program wants to redirect its stdin (e.g., because it is
forking and exec'ing a child). So it calls dup2(fd, 0), closing
what was at stdin previously, which might have been valuable.
The right thing to do is to redirect stdin from /dev/null, not close
it
entirely.
Ah, yes, that's a normal thing I would think about in C. In Perl,
I imagined that those details were handled by Perl.
With that in mind, I'm still seeing strange behavior when I do this,
where it looks to me like I'm closing and then immediately assigning
STDIN:
my $null_in_fh;
open($null_in_fh, '<', '/dev/null') or die;
close *STDIN; # this appears to mess things up, even with the
following assignment
*STDIN = $null_in_fh;
But if I don't do the close STDIN (with or without the glob), then
things work.
Maybe that assignment doesn't work for some Perl-ish reason.
Because, if I just do this
open(STDIN, '<', '/dev/null') or die;
even after the close and/or assignment, then all appears okay.
I'll stick with this last technique and just chalk it up to something
to something about Perl I don't understand. (I had the idea that
maybe I wanted to redirect /dev/null to STDIN at some point anyway.)
Thanks for your comments.
-Travis
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html