]> Sergey Matveev's repositories - public-inbox.git/commitdiff
lei: fix git-credential handling
authorEric Wong <e@80x24.org>
Fri, 2 Apr 2021 09:42:54 +0000 (05:42 -0400)
committerEric Wong <e@80x24.org>
Fri, 2 Apr 2021 21:03:44 +0000 (17:03 -0400)
I completely forgot about git-credential prompting when
making lei background the client process for MUA.

Now it backgrounds itself only for the MUA when no FDs are
passed, since the MUA is the final command run.  Otherwise, it
relies on FD passing as before.

Fixes: c790a75439f3a1db ("script/lei: background ourselves on MUA/pager exec")
lib/PublicInbox/LEI.pm
script/lei

index 69d48bd1b2da048f59e8311a990fa88917cc106e..f9361c68240fac3f331ea01fa130b6603eefb249 100644 (file)
@@ -839,7 +839,13 @@ sub start_mua {
        if (my $sock = $self->{sock}) { # lei(1) client process runs it
                send($sock, exec_buf(\@cmd, {}), MSG_EOR);
        } elsif ($self->{oneshot}) {
-               $self->{"pid.$self.$$"}->{spawn(\@cmd)} = \@cmd;
+               my $pid = fork // die "fork: $!";
+               if ($pid > 0) { # original process
+                       exec(@cmd);
+                       warn "exec @cmd: $!\n";
+                       POSIX::_exit(1);
+               }
+               POSIX::setsid() > 0 or die "setsid: $!";
        }
        if ($self->{lxs} && $self->{au_done}) { # kick wait_startq
                syswrite($self->{au_done}, 'q' x ($self->{lxs}->{jobs} // 0));
index bea8dcde97ea1be5662f4a02803137ca981bafbb..78a7dab9b1a634e61cb45a73b5f1dc8732cd77cf 100755 (executable)
@@ -14,31 +14,45 @@ my $send_cmd = PublicInbox::CmdIPC4->can('send_cmd4') // do {
        PublicInbox::Spawn->can('send_cmd4');
 };
 
-my @orig_pid;
+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 @parent;
 my $exec_cmd = sub {
        my ($fds, $argc, @argv) = @_;
-       die "BUG: already exec-ed\n" if @orig_pid;
-       @orig_pid = ($$);
-       require POSIX; # WNOHANG
+       my $parent = $$;
+       require POSIX;
        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;
+               open(my $newfh, '+<&=', $fd) or die "open +<&=$fd: $!";
+               push @rdr, shift(@old), $newfh;
        }
+       my $do_exec = sub {
+               my %env = map { split(/=/, $_, 2) } splice(@argv, $argc);
+               @ENV{keys %env} = values %env;
+               exec(@argv);
+               warn "exec: @argv: $!\n";
+               POSIX::_exit(1);
+       };
+       $SIG{CHLD} = $sigchld;
        my $pid = fork // die "fork: $!";
        if ($pid == 0) {
+               while (my ($io, $newfh) = splice(@rdr, 0, 2)) {
+                       open $io, '+<&', $newfh or die "open +<&=: $!";
+               }
+               $do_exec->() if scalar(@$fds); # git-credential, pager
+
+               # parent backgrounds on MUA
                POSIX::setsid() > 0 or die "setsid: $!";
+               @parent = ($parent);
                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 +<&=: $!";
-       }
-       @ENV{keys %env} = values %env;
-       exec(@argv);
-       warn "exec: @argv: $!\n";
-       POSIX::_exit(1);
+       $do_exec->() if !scalar(@$fds); # MUA reuses all FDs
 };
 
 if ($send_cmd && eval {
@@ -95,16 +109,18 @@ Falling back to (slow) one-shot mode
                if ($buf =~ /\Aexec (.+)\z/) {
                        $exec_cmd->(\@fds, split(/\0/, $1));
                } elsif ($buf eq '-WINCH') {
-                       kill($buf, @orig_pid); # for MUA
+                       kill($buf, @parent); # 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;