From c790a75439f3a1dbbaa2162feca2593de5997bd3 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Wed, 31 Mar 2021 23:29:36 +0000 Subject: script/lei: background ourselves on MUA/pager exec This ought to give the MUA or pager exclusive access to the controlling terminal. The downside is we can only exec the pager or MUA once per invocation, but I can't imagine a valid case for running those things multiple times, either. Note: I'm no expert when it comes to terminal control matters, but this allows Ctrl-Z-ed mutt instance to come back and is a nice code reduction, as well. --- script/lei | 37 +++++++++++++++---------------------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/script/lei b/script/lei index cb605e2e..bea8dcde 100755 --- a/script/lei +++ b/script/lei @@ -14,36 +14,31 @@ my $send_cmd = PublicInbox::CmdIPC4->can('send_cmd4') // do { PublicInbox::Spawn->can('send_cmd4'); }; -my %pids; -my $sigchld = sub { - my $flags = scalar(@_) ? POSIX::WNOHANG() : 0; - for my $pid (keys %pids) { - delete($pids{$pid}) if waitpid($pid, $flags) == $pid; - } -}; - +my @orig_pid; my $exec_cmd = sub { my ($fds, $argc, @argv) = @_; + die "BUG: already exec-ed\n" if @orig_pid; + @orig_pid = ($$); + require POSIX; # WNOHANG my @old = (*STDIN{IO}, *STDOUT{IO}, *STDERR{IO}); my @rdr; for my $fd (@$fds) { open(my $tmpfh, '+<&=', $fd) or die "open +<&=$fd: $!"; push @rdr, shift(@old), $tmpfh; } - require POSIX; # WNOHANG - $SIG{CHLD} = $sigchld; my $pid = fork // die "fork: $!"; if ($pid == 0) { - my %env = map { split(/=/, $_, 2) } splice(@argv, $argc); - while (my ($old_io, $tmpfh) = splice(@rdr, 0, 2)) { - open $old_io, '+<&', $tmpfh or die "open +<&=: $!"; - } - %ENV = (%ENV, %env); - exec(@argv); - warn "exec: @argv: $!\n"; - POSIX::_exit(1); + POSIX::setsid() > 0 or die "setsid: $!"; + return; # continue $recv_cmd in background + } + my %env = map { split(/=/, $_, 2) } splice(@argv, $argc); + while (my ($old_io, $tmpfh) = splice(@rdr, 0, 2)) { + open $old_io, '+<&', $tmpfh or die "open +<&=: $!"; } - $pids{$pid} = 1; + @ENV{keys %env} = values %env; + exec(@argv); + warn "exec: @argv: $!\n"; + POSIX::_exit(1); }; if ($send_cmd && eval { @@ -100,18 +95,16 @@ Falling back to (slow) one-shot mode if ($buf =~ /\Aexec (.+)\z/) { $exec_cmd->(\@fds, split(/\0/, $1)); } elsif ($buf eq '-WINCH') { - kill($buf, $$); # for MUA + kill($buf, @orig_pid); # for MUA } elsif ($buf =~ /\Ax_it ([0-9]+)\z/) { $x_it_code = $1 + 0; last; } elsif ($buf =~ /\Achild_error ([0-9]+)\z/) { $x_it_code = $1 + 0; } else { - $sigchld->(); die $buf; } } - $sigchld->(); if (my $sig = ($x_it_code & 127)) { kill $sig, $$; sleep(1) while 1; -- cgit v1.2.3-24-ge0c7