From aaeae21a54bd4d288b91821c5f3d9234d090ebd5 Mon Sep 17 00:00:00 2001 From: "Kyle J. McKay" Date: Sun, 27 Jun 2021 16:13:30 -0700 Subject: [PATCH] Util.pm/CLIUtil.pm: clean up abnormal exit code handling When the setup_pager function arranges for STDOUT to be paged, it was causing the exit code of the process (when using the special "become child" feature) to be that of the pager rather than the program itself. Fix this to capture the exit status of the real program and then exit with that value instead. When the noFatalsToBrowser function disables the CGI redirection of die from the unreadable-when-dumped-on-the-terminal output to something more legible, it inspects the various error variables to determine what exit code it should use (if it's not in an eval block). In both of these cases, be careful to make sure that the exit code used is in the range 0..255 inclusive and furthermore, that if the exit was caused by a signal that it's the 128+signal_num value rather than the bare signal_num value. Force unexpected exit codes outside the 0.255 range to be 255. Signed-off-by: Kyle J. McKay --- Girocco/CLIUtil.pm | 29 +++++++++++++++++++++++++---- Girocco/Util.pm | 2 ++ 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/Girocco/CLIUtil.pm b/Girocco/CLIUtil.pm index ec23a11..b972928 100644 --- a/Girocco/CLIUtil.pm +++ b/Girocco/CLIUtil.pm @@ -654,7 +654,9 @@ sub nice_me { # if the first argument is the string "become child", # then, if a pager is created, the child will return # to the caller and the parent will exec the pager! -# (The returned pid in that case is the parent's pid.) +# (The returned pid in that case is the parent's pid +# and the parent waits for the child to finish to propagate +# its exit status as the final exit value.) sub setup_pager { my $magic = $_[0]; defined($magic) && lc($magic) eq "become child" or @@ -699,9 +701,28 @@ sub setup_pager { POSIX::close($wfd); POSIX::dup2($rfd, 0); POSIX::close($rfd); - $magic and $SIG{CHLD} = 'IGNORE'; - exec {$cmd[0]} @cmd or - die "exec \"$cmd[0]\" failed: $!\n"; + if (!$magic) { + exec {$cmd[0]} @cmd or + die "exec \"$cmd[0]\" failed: $!\n"; + } + my $pagerpid = fork(); + defined($pagerpid) or + die "fork failed: $!\n"; + if (!$pagerpid) { + exec {$cmd[0]} @cmd or + die "exec \"$cmd[0]\" failed: $!\n"; + } + my $wc = undef; + for (;;) { + my $child = wait; + last if $child == -1; + $child == $pid and $wc = $?; + } + defined($wc) or exit 255; + my $ec = $wc >> 8; + $ec != ($ec & 0xff) and $ec = 255; + $ec |= 128 if $wc & 0xff; + exit $ec; } $magic and $pid = getppid(); POSIX::close($rfd); diff --git a/Girocco/Util.pm b/Girocco/Util.pm index 21e981e..a82132c 100644 --- a/Girocco/Util.pm +++ b/Girocco/Util.pm @@ -994,6 +994,8 @@ sub noFatalsToBrowser { *CORE::GLOBAL::die = sub { no warnings; my $ec = (0+$!) || ($? >> 8) || 255; + $ec != ($ec & 0xff) and $ec = 255; + $ec |= 128 if !(0+$!) && ($? & 0xff); my (undef, $fn, $li) = caller(0); my $loc = " at " . $fn . " line " . $li . ".\n"; my $msg = ""; -- 2.11.4.GIT