summaryrefslogtreecommitdiff
path: root/perl5
diff options
context:
space:
mode:
authorSean Whitton <spwhitton@spwhitton.name>2020-04-14 23:45:50 -0700
committerSean Whitton <spwhitton@spwhitton.name>2020-04-14 23:45:50 -0700
commit2d23e1708b42b17da7e333e7aee8f992854b0e9a (patch)
treedb9d169b85ed7f3e07d0fd43cb177063478fbba6 /perl5
parent249e5fcc21d4a2b60364c6250f5d4129d87d4fc3 (diff)
downloaddotfiles-2d23e1708b42b17da7e333e7aee8f992854b0e9a.tar.gz
_sysptycap_tty: avoid getting stuck on sysread
Diffstat (limited to 'perl5')
-rw-r--r--perl5/Local/Interactive.pm23
1 files changed, 19 insertions, 4 deletions
diff --git a/perl5/Local/Interactive.pm b/perl5/Local/Interactive.pm
index 50f3e06a..0cd6e912 100644
--- a/perl5/Local/Interactive.pm
+++ b/perl5/Local/Interactive.pm
@@ -25,7 +25,7 @@ use Exporter 'import';
use Term::ANSIColor;
use Local::ScriptStatus;
use Sys::Hostname;
-use POSIX ();
+use POSIX ":sys_wait_h";
# Quoting perldoc perlmodlib: "As a general rule, if the module is
# trying to be object oriented then export nothing. If it's just a
@@ -216,15 +216,30 @@ sub _sysptycap_tty {
}
$pty->close;
my $output;
- while (1) {
+ # don't continue trying to read if child has died. This is needed
+ # as the child might die without the pty getting EOF, e.g. if an
+ # SSH control socket is still alive (seems to happen when using
+ # Debian's SSH jump host to SSH to salsa)
+ while (kill 0, $pid) {
my ($chars, $nchars);
- $nchars = sysread $slave, $chars, 8192;
+ local $@;
+ eval {
+ local $SIG{ALRM} = sub { die "sysread timeout\n" };
+ alarm 1;
+ $nchars = sysread $slave, $chars, 8192;
+ alarm 0;
+ };
+ if (my $exception = $@) {
+ die $exception unless $exception eq "sysread timeout\n";
+ # since it's stopped emitting output, see if child needs
+ # reaping
+ waitpid -1, &WNOHANG;
+ }
last if defined $nchars and $nchars == 0;
print $chars;
$output .= $chars;
}
$slave->close;
- wait;
exit 2 if $interrupted;
return { exit => $? >> 8, output => $output };
}