Skip to content

Commit 62c71ac

Browse files
peffgitster
authored andcommitted
test-terminal: drop stdin handling
Since 18d8c26 (test_terminal: redirect child process' stdin to a pty, 2015-08-04), we set up a pty and copy stdin to the child program. But this ends up being racy; once we send all of the bytes and close the descriptor, the child program will no longer see a terminal! isatty() will return 0, and trying to read may return EIO, even if we didn't yet get all of the bytes. This was mentioned even in the commit message of 18d8c26, but we hacked around it by just sending an infinite input from /dev/zero (in the intended case, we only cared about isatty(0), not reading actual input). And it came up again recently in: https://lore.kernel.org/git/[email protected]/ where we tried to actually send bytes, but they don't always all come through. So this interface is somewhat of an accident waiting to happen; a caller might not even care about stdin being a tty, but will get bit by the flaky behavior. One solution would probably be to avoid closing test_terminal's end of the pty altogether. But then the other side would never see EOF on its stdin. That may be OK for some cases, but it's another gotcha that might cause races or deadlocks, depending on what the child expects to read. Let's instead just drop test_terminal's stdin feature completely. Since the previous commit dropped the two cases from t4153 for which the feature was originally added, there are no callers left that need it. Signed-off-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 53ce2e3 commit 62c71ac

File tree

1 file changed

+3
-26
lines changed

1 file changed

+3
-26
lines changed

t/test-terminal.perl

Lines changed: 3 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,15 @@
55
use IO::Pty;
66
use File::Copy;
77

8-
# Run @$argv in the background with stdio redirected to $in, $out and $err.
8+
# Run @$argv in the background with stdio redirected to $out and $err.
99
sub start_child {
10-
my ($argv, $in, $out, $err) = @_;
10+
my ($argv, $out, $err) = @_;
1111
my $pid = fork;
1212
if (not defined $pid) {
1313
die "fork failed: $!"
1414
} elsif ($pid == 0) {
15-
open STDIN, "<&", $in;
1615
open STDOUT, ">&", $out;
1716
open STDERR, ">&", $err;
18-
close $in;
1917
close $out;
2018
exec(@$argv) or die "cannot exec '$argv->[0]': $!"
2119
}
@@ -51,17 +49,6 @@ sub xsendfile {
5149
copy($in, $out, 4096) or $!{EIO} or die "cannot copy from child: $!";
5250
}
5351

54-
sub copy_stdin {
55-
my ($in) = @_;
56-
my $pid = fork;
57-
if (!$pid) {
58-
xsendfile($in, \*STDIN);
59-
exit 0;
60-
}
61-
close($in);
62-
return $pid;
63-
}
64-
6552
sub copy_stdio {
6653
my ($out, $err) = @_;
6754
my $pid = fork;
@@ -81,25 +68,15 @@ sub copy_stdio {
8168
die "usage: test-terminal program args";
8269
}
8370
$ENV{TERM} = 'vt100';
84-
my $parent_in = new IO::Pty;
8571
my $parent_out = new IO::Pty;
8672
my $parent_err = new IO::Pty;
87-
$parent_in->set_raw();
8873
$parent_out->set_raw();
8974
$parent_err->set_raw();
90-
$parent_in->slave->set_raw();
9175
$parent_out->slave->set_raw();
9276
$parent_err->slave->set_raw();
93-
my $pid = start_child(\@ARGV, $parent_in->slave, $parent_out->slave, $parent_err->slave);
94-
close $parent_in->slave;
77+
my $pid = start_child(\@ARGV, $parent_out->slave, $parent_err->slave);
9578
close $parent_out->slave;
9679
close $parent_err->slave;
97-
my $in_pid = copy_stdin($parent_in);
9880
copy_stdio($parent_out, $parent_err);
9981
my $ret = finish_child($pid);
100-
# If the child process terminates before our copy_stdin() process is able to
101-
# write all of its data to $parent_in, the copy_stdin() process could stall.
102-
# Send SIGTERM to it to ensure it terminates.
103-
kill 'TERM', $in_pid;
104-
finish_child($in_pid);
10582
exit($ret);

0 commit comments

Comments
 (0)