Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hello all, I'm somewhat new to IPC and about to go crazy. In my program there is a LOG handle for recording what happens. In one subroutine where I want to be really meticulous with how I handle errors, I redirect STDERR from a pipe into a file, err.log. If upon successful pipe opening there is content in err.log, I want to: A)print a warning to the standard log B)exit the entire program, while printing "Killed" to the screen. Well, with the code below, I get err.log populated, but nothing is printed to the screen. And no, "Killed" is not printed to err.log either. Worst of all, the die, if it's being executed at all, seems to only be exiting the subroutine, because print statements from other_code() are printed to my standard log. I'm getting really REALLY frustrated with the intricacies of pipes, handle redirection/selection/closing, and autoflushing, having worked on this for the last few hours. Could someone PLEASE sort me out. Thanks so much. Below is skeleton code without all my failed experimentation, just so you can see what my intent is.
open LOG ">>std.log" or die $!; im_missing_something_here(); other_calls(); close LOG; sub im_missing_something_here { open STDERR, ">>err.log" or die $!; # Perl can run the shell # if (open(PIPE, "$cmd <$tempfile |")) { # but there is a message in STDERR # if (-s './err.log') { print LOG "ERROR:see err.log, exiting..\n"; close STDERR; die "Killed.\n"; #to default STDERR is intent } ... }

Replies are listed 'Best First'.
Re: Why is this not dying
by Thelonius (Priest) on Apr 02, 2003 at 20:28 UTC
    Well, of course. You just closed STDERR so anything printed to it will be lost. If you really want to go back to the original STDERR you will have to save a copy of the file handle, either using dup() or the equivalent "open" parameters. E.g.
    open SAVEERR, ">&STDERR"; open STDERR, ">>err.log" or die "err.log: $!\n"; ... close STDERR; open STDERR, ">&SAVEERR";
      Thanks ever so much. Your reply was part of the solution. Interestingly, the reason why the die was never executed (much less displayed anywhere) was because of an apparent race condition(?) between writing to the err.log and testing its size. In the following if (-z...) conditional, a print "you missed errlog size" statement would be printed, despite the fact that a check afterwards showed that err.log contained the lines I was expecting for the test case. A bit of sleep chicanery was required. So this works as desired:
      open SAVERR, ">&STDERR"; open STDERR, ">>err.log"; # Perl can run the shell # if (open(PIPE, "$cmd <$tempfile |")) { sleep(2); if (-z './err.log') { close SAVERR; process(*PIPE); } # but there is a message in STDERR # else { # print LOG "ERROR: see err.log, exiting...\n"; # close STDERR; open STDERR, ">&SAVERR"; die "Killed.\n"; } }