From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on dcvr.yhbt.net X-Spam-Level: X-Spam-Status: No, score=-4.0 required=3.0 tests=ALL_TRUSTED,BAYES_00 shortcircuit=no autolearn=ham autolearn_force=no version=3.4.2 Received: from localhost (dcvr.yhbt.net [127.0.0.1]) by dcvr.yhbt.net (Postfix) with ESMTP id 40BC91FA18 for ; Fri, 18 Dec 2020 12:09:51 +0000 (UTC) From: Eric Wong To: meta@public-inbox.org Subject: [PATCH 05/26] lei: use spawn (vfork + execve) for lazy start Date: Fri, 18 Dec 2020 12:09:29 +0000 Message-Id: <20201218120950.23272-6-e@80x24.org> In-Reply-To: <20201218120950.23272-1-e@80x24.org> References: <20201218120950.23272-1-e@80x24.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit List-Id: 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 | 12 +++++------- script/lei | 14 ++++++++++---- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/lib/PublicInbox/LeiDaemon.pm b/lib/PublicInbox/LeiDaemon.pm index b4b1ac59..fd4d00d4 100644 --- a/lib/PublicInbox/LeiDaemon.pm +++ b/lib/PublicInbox/LeiDaemon.pm @@ -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; diff --git a/script/lei b/script/lei index 1b5af3a1..637c1951 100755 --- a/script/lei +++ b/script/lei @@ -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();