]> Sergey Matveev's repositories - public-inbox.git/commitdiff
lei: use spawn (vfork + execve) for lazy start
authorEric Wong <e@80x24.org>
Tue, 15 Dec 2020 09:03:34 +0000 (09:03 +0000)
committerEric Wong <e@80x24.org>
Sat, 19 Dec 2020 09:32:08 +0000 (09:32 +0000)
This allows us to rely on FD_CLOEXEC being set on pipes
from prove(1), so forgetting `daemon-stop' won't cause
tests to hang.

Unfortunately, daemon tests will be slower with this.

lib/PublicInbox/LeiDaemon.pm
script/lei

index b4b1ac598ce094b3ff7784d1574d4060d682d961..fd4d00d421dd9dce375669136411ccadfc38a352 100644 (file)
@@ -324,29 +324,27 @@ sub accept_dispatch { # Listener {post_accept} callback
 sub noop {}
 
 # lei(1) calls this when it can't connect
-sub lazy_start ($$) {
+sub lazy_start {
        my ($path, $err) = @_;
        if ($err == ECONNREFUSED) {
                unlink($path) or die "unlink($path): $!";
        } elsif ($err != ENOENT) {
                die "connect($path): $!";
        }
+       require IO::FDPass;
        my $umask = umask(077) // die("umask(077): $!");
        my $l = IO::Socket::UNIX->new(Local => $path,
                                        Listen => 1024,
                                        Type => SOCK_STREAM) or
                $err = $!;
        umask($umask) or die("umask(restore): $!");
-       $l or return $err;
+       $l or return die "bind($path): $err";
        my @st = stat($path) or die "stat($path): $!";
        my $dev_ino_expect = pack('dd', $st[0], $st[1]); # dev+ino
        pipe(my ($eof_r, $eof_w)) or die "pipe: $!";
        my $oldset = PublicInbox::Sigfd::block_signals();
        my $pid = fork // die "fork: $!";
-       if ($pid) {
-               PublicInbox::Sigfd::sig_setmask($oldset);
-               return; # client will connect to $path
-       }
+       return if $pid;
        openlog($path, 'pid', 'user');
        local $SIG{__DIE__} = sub {
                syslog('crit', "@_");
@@ -360,7 +358,7 @@ sub lazy_start ($$) {
        open STDERR, '>&STDIN' or die "redirect stderr failed: $!\n";
        setsid();
        $pid = fork // die "fork: $!";
-       exit if $pid;
+       return if $pid;
        $0 = "lei-daemon $path";
        require PublicInbox::Listener;
        require PublicInbox::EOFpipe;
index 1b5af3a1cc1b2f0b8127aeb58f337c16310e3551..637c19513105ba5d0de2d6e75f7bae77119ff83b 100755 (executable)
@@ -21,13 +21,19 @@ if (eval { require IO::FDPass; 1 }) { # use daemon to reduce load time
        };
        my $sock = IO::Socket::UNIX->new(Peer => $path, Type => SOCK_STREAM);
        unless ($sock) { # start the daemon if not started
-               my $err = $!;
-               require PublicInbox::LeiDaemon;
-               $err = PublicInbox::LeiDaemon::lazy_start($path, $err);
+               my $err = $! + 0;
+               my $env = { PERL5LIB => join(':', @INC) };
+               my $cmd = [ $^X, qw[-MPublicInbox::LeiDaemon
+                       -E PublicInbox::LeiDaemon::lazy_start(@ARGV)],
+                       $path, $err ];
+               require PublicInbox::Spawn;
+               waitpid(PublicInbox::Spawn::spawn($cmd, $env), 0);
+               warn "lei-daemon exited with \$?=$?\n" if $?;
+
                # try connecting again anyways, unlink+bind may be racy
                $sock = IO::Socket::UNIX->new(Peer => $path,
                                                Type => SOCK_STREAM) // die
-                       "connect($path): $! (bind($path): $err)";
+                       "connect($path): $! (after attempted daemon start)";
        }
        my $pwd = $ENV{PWD};
        my $cwd = cwd();