about summary refs log tree commit homepage
path: root/script
diff options
context:
space:
mode:
authorEric Wong <e@80x24.org>2020-12-17 23:54:04 +0000
committerEric Wong <e@80x24.org>2020-12-19 09:32:08 +0000
commitf2c7b911a1c4a7520091ba7224773c30e409c337 (patch)
tree576386c92369a5f3f1005f68b18b4d6be1470b17 /script
parentcf731a1422064344f25c214670fb0007ab1d4c2c (diff)
downloadpublic-inbox-f2c7b911a1c4a7520091ba7224773c30e409c337.tar.gz
We'll force stdout+stderr to be a pipe the spawning client
controls, thus there's no need to lose error reporting by
prematurely redirecting stdout+stderr to /dev/null.

We can now rely exclusively on OnDestroy to write to syslog() on
uncaught die failures.

Also support falling back to oneshot mode on socket and cwd
failures, since some commands may still be useful if the current
working directory goes missing :P
Diffstat (limited to 'script')
-rwxr-xr-xscript/lei39
1 files changed, 25 insertions, 14 deletions
diff --git a/script/lei b/script/lei
index 2b041fb4..ceaf1e00 100755
--- a/script/lei
+++ b/script/lei
@@ -4,8 +4,8 @@
 use strict;
 use v5.10.1;
 use Socket qw(AF_UNIX SOCK_STREAM pack_sockaddr_un);
-
-if (eval { require IO::FDPass; 1 }) { # use daemon to reduce load time
+if (my ($sock, $pwd) = eval {
+        require IO::FDPass; # will try to use a daemon to reduce load time
         my $path = do {
                 my $runtime_dir = ($ENV{XDG_RUNTIME_DIR} // '') . '/lei';
                 if ($runtime_dir eq '/lei') {
@@ -21,32 +21,41 @@ if (eval { require IO::FDPass; 1 }) { # use daemon to reduce load time
         my $addr = pack_sockaddr_un($path);
         socket(my $sock, AF_UNIX, SOCK_STREAM, 0) or die "socket: $!";
         unless (connect($sock, $addr)) { # start the daemon if not started
-                my $err = $! + 0;
-                my $env = { PERL5LIB => join(':', @INC) };
                 my $cmd = [ $^X, qw[-MPublicInbox::LEI
                         -E PublicInbox::LEI::lazy_start(@ARGV)],
-                        $path, $err ];
+                        $path, $! + 0 ];
+                my $env = { PERL5LIB => join(':', @INC) };
+                pipe(my ($daemon, $w)) or die "pipe: $!";
+                my $opt = { 1 => $w, 2 => $w };
                 require PublicInbox::Spawn;
-                waitpid(PublicInbox::Spawn::spawn($cmd, $env), 0);
-                warn "lei-daemon exited with \$?=$?\n" if $?;
+                my $pid = PublicInbox::Spawn::spawn($cmd, $env, $opt);
+                $opt = $w = undef;
+                while (<$daemon>) { warn $_ } # EOF when STDERR is redirected
+                waitpid($pid, 0) or warn <<"";
+lei-daemon could not start, PID:$pid exited with \$?=$?
 
                 # try connecting again anyways, unlink+bind may be racy
-                connect($sock, $addr) or die
-                        "connect($path): $! (after attempted daemon start)";
+                unless (connect($sock, $addr)) {
+                        die <<"";
+connect($path): $! (after attempted daemon start)
+Falling back to (slow) one-shot mode
+
+                }
         }
         require Cwd;
-        my $cwd = Cwd::fastcwd() // die "fastcwd: $!";
+        my $cwd = Cwd::fastcwd() // die "fastcwd(PWD=".($ENV{PWD}//'').": $!";
         my $pwd = $ENV{PWD} // '';
-        if ($pwd eq $cwd) { # likely, all good
-        } elsif ($pwd) { # prefer ENV{PWD} if it's a symlink to real cwd
-                my @st_cwd = stat($cwd) or die "stat(cwd=$cwd): $!\n";
-                my @st_pwd = stat($pwd);
+        if ($pwd ne $cwd) { # prefer ENV{PWD} if it's a symlink to real cwd
+                my @st_cwd = stat($cwd) or die "stat(cwd=$cwd): $!";
+                my @st_pwd = stat($pwd); # PWD invalid, use cwd
                 # make sure st_dev/st_ino match for {PWD} to be valid
                 $pwd = $cwd if (!@st_pwd || $st_pwd[1] != $st_cwd[1] ||
                                         $st_pwd[0] != $st_cwd[0]);
         } else {
                 $pwd = $cwd;
         }
+        ($sock, $pwd);
+}) { # IO::FDPass, $sock, $pwd are all available:
         local $ENV{PWD} = $pwd;
         my $buf = "$$\0\0>" . join("]\0[", @ARGV) . "\0\0>";
         while (my ($k, $v) = each %ENV) { $buf .= "$k=$v\0" }
@@ -60,6 +69,8 @@ if (eval { require IO::FDPass; 1 }) { # use daemon to reduce load time
                 die $buf;
         }
 } else { # for systems lacking IO::FDPass
+        # don't warn about IO::FDPass since it's not commonly installed
+        warn $@ if $@ && index($@, 'IO::FDPass') < 0;
         require PublicInbox::LEI;
         PublicInbox::LEI::oneshot(__PACKAGE__);
 }