Subject: | IPC::Run modifies STDOUT buffering |
Date: | Fri, 20 Nov 2015 10:37:46 -0800 |
To: | bug-IPC-Run [...] rt.cpan.org |
From: | Sam Huffman <shuffman [...] gmail.com> |
Hi, We just found an issue in IPC::Run. The issue is that if prior to a
run() call STDOUT (or the default filehandle) is unbuffered, run() will
restore it to a buffered state. I've verified this bug exists in 0.94, and
across all perl versions from 5.5 - 5.20; we're using SLES11 Linux, but the
issue is independent of linux version.
% cat test5
#!/usr/intel/pkgs/perl/5.14.1/bin/perl -w
use IPC::Run;
STDOUT->autoflush();
printf "AUTOFLUSH %s: %d\n", select, $|;
IPC::Run::run(['/bin/hostname'], '1>', "/dev/null", '2>', "/dev/null");
printf "AUTOFLUSH %s: %d\n", select, $|;
% ./test5
AUTOFLUSH main::STDOUT: 1
AUTOFLUSH main::STDOUT: 0
The two lines that contain the bug are here:
## This is a bit of a hack, we should do it for all open filehandles.
## Since there's no way I know of to enumerate open filehandles, we
## autoflush STDOUT and STDERR. This is done so that the children don't
## inherit output buffers chock full o' redundant data. It's really
## confusing to track that down.
{ my $ofh = select STDOUT; local $| = 1; select $ofh; }
{ my $ofh = select STDERR; local $| = 1; select $ofh; }
Here's a sample perl script showing the issue:
% cat test4
#!/usr/bin/perl -w
STDOUT->autoflush();
printf "AUTOFLUSH %s: %d\n", select, $|;
{ my $ofh = select STDOUT; local $| = 1; select $ofh; }
{ my $ofh = select STDERR; local $| = 1; select $ofh; }
printf "AUTOFLUSH %s: %d\n", select, $|;
% ./test4
AUTOFLUSH main::STDOUT: 1
AUTOFLUSH main::STDOUT: 0
The issue is that STDERR's *previous* buffer value gets restored into $ofh
(STDOUT, in our case) when the block exits, resulting in STDOUT being
buffered.
Thanks!
Sam