From 8d29cf132caf3de81986179b10746f31123c96b9 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Thu, 19 Dec 2019 08:38:51 +0000 Subject: testcommon: fix run_script for older Perls Using Perl "open" to dup(2) and save the old handles is required since "local *STDIN = *STDIN" does not work on old Perls. Even worse, this was silently a no-op when tested with Perl 5.24.1 on Debian 9.x and led to confusing failures in the t/httpd-corner.t lsof(1) tests when run after t/v2mirror.t from the same worker process using t/run.perl. --- lib/PublicInbox/TestCommon.pm | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) (limited to 'lib/PublicInbox/TestCommon.pm') diff --git a/lib/PublicInbox/TestCommon.pm b/lib/PublicInbox/TestCommon.pm index 85cda031..2828c0d0 100644 --- a/lib/PublicInbox/TestCommon.pm +++ b/lib/PublicInbox/TestCommon.pm @@ -67,12 +67,27 @@ sub key2script ($) { 'blib/script/'.$key; } +my @io_mode = ([ *STDIN{IO}, '<&' ], [ *STDOUT{IO}, '>&' ], + [ *STDERR{IO}, '>&' ]); + sub _prepare_redirects ($) { my ($fhref) = @_; - my @x = ([ \*STDIN, '<&' ], [ \*STDOUT, '>&' ], [ \*STDERR, '>&' ]); - for (my $fd = 0; $fd <= $#x; $fd++) { + my $orig_io = []; + for (my $fd = 0; $fd <= $#io_mode; $fd++) { my $fh = $fhref->[$fd] or next; - my ($oldfh, $mode) = @{$x[$fd]}; + my ($oldfh, $mode) = @{$io_mode[$fd]}; + open my $orig, $mode, $oldfh or die "$$oldfh $mode stash: $!"; + $orig_io->[$fd] = $orig; + open $oldfh, $mode, $fh or die "$$oldfh $mode redirect: $!"; + } + $orig_io; +} + +sub _undo_redirects ($) { + my ($orig_io) = @_; + for (my $fd = 0; $fd <= $#io_mode; $fd++) { + my $fh = $orig_io->[$fd] or next; + my ($oldfh, $mode) = @{$io_mode[$fd]}; open $oldfh, $mode, $fh or die "$$oldfh $mode redirect: $!"; } } @@ -174,14 +189,14 @@ sub run_script ($;$$) { $r == $pid or die "waitpid: expected $pid, got $r"; } } else { # localize and run everything in the same process: - local *STDIN = *STDIN; - local *STDOUT = *STDOUT; - local *STDERR = *STDERR; + # note: "local *STDIN = *STDIN;" and so forth did not work in + # old versions of perl local %ENV = $env ? (%ENV, %$env) : %ENV; local %SIG = %SIG; local $0 = join(' ', @$cmd); - _prepare_redirects($fhref); + my $orig_io = _prepare_redirects($fhref); _run_sub($sub, $key, \@argv); + _undo_redirects($orig_io); } # slurp the redirects back into user-supplied strings -- cgit v1.2.3-24-ge0c7