| | 49 | } |
|---|
| | 50 | |
|---|
| | 51 | # map process termination status number to a string, and append optional |
|---|
| | 52 | # user error mesage, returning the resulting string |
|---|
| | 53 | sub exit_status_str($;$) { |
|---|
| | 54 | my($stat,$err) = @_; my($str); |
|---|
| | 55 | if (WIFEXITED($stat)) { |
|---|
| | 56 | $str = sprintf("exit %d", WEXITSTATUS($stat)); |
|---|
| | 57 | } elsif (WIFSTOPPED($stat)) { |
|---|
| | 58 | $str = sprintf("stopped, signal %d", WSTOPSIG($stat)); |
|---|
| | 59 | } else { |
|---|
| | 60 | $str = sprintf("DIED on signal %d (%04x)", WTERMSIG($stat),$stat); |
|---|
| | 61 | } |
|---|
| | 62 | $str .= ', '.$err if defined $err && $err != 0; |
|---|
| | 63 | $str; |
|---|
| | 64 | } |
|---|
| | 65 | |
|---|
| | 66 | # POSIX::open a file or dup an existing fd (Perl open syntax), with a |
|---|
| | 67 | # requirement that it gets opened on a prescribed file descriptor $fd_target; |
|---|
| | 68 | # this subroutine is usually called from a forked process prior to exec |
|---|
| | 69 | sub open_on_specific_fd($$) { |
|---|
| | 70 | my($fd_target,$fname) = @_; |
|---|
| | 71 | my($flags) = 0; my($mode) = 0640; |
|---|
| | 72 | $fname =~ s/^< *//; |
|---|
| | 73 | $fname =~ s/^>> *// and $flags |= O_CREAT|O_WRONLY|O_APPEND; |
|---|
| | 74 | $fname =~ s/^> *// and $flags |= O_CREAT|O_WRONLY|O_EXCL; |
|---|
| | 75 | POSIX::close($fd_target); # ignore error, we may have just closed a log |
|---|
| | 76 | my($fd_got) = POSIX::open($fname,$flags,$mode); |
|---|
| | 77 | defined $fd_got or die "Can't open $fname, flags=$flags: $!"; |
|---|
| | 78 | $fd_got = 0 + $fd_got; # turn into numeric, avoid: "0 but true" |
|---|
| | 79 | if ($fd_got != $fd_target) { # dup, ensuring we get a specified descriptor |
|---|
| | 80 | # POSIX mandates we got the lowest fd available (but some kernels have |
|---|
| | 81 | # bugs), let's be explicit that we require a specified file descriptor |
|---|
| | 82 | defined POSIX::dup2($fd_got,$fd_target) |
|---|
| | 83 | or "Can't dup2 from $fd_got to $fd_target: $!"; |
|---|
| | 84 | if ($fd_got > 2) { # let's get rid of the original fd, unless 0,1,2 |
|---|
| | 85 | my($err); defined POSIX::close($fd_got) or $err = $!; |
|---|
| | 86 | $err = defined $err ? ": $err" : ''; |
|---|
| | 87 | } |
|---|
| | 88 | } |
|---|
| | 89 | $fd_got; |
|---|
| 75 | | open(STDERR, $stderr); |
|---|
| 76 | | } |
|---|
| 77 | | exec($cmd) and exit($?); |
|---|
| 78 | | exit(-2); |
|---|
| | 123 | open_on_specific_fd(2, $stderr); |
|---|
| | 124 | } |
|---|
| | 125 | exec($cmd); |
|---|
| | 126 | die "failed to exec $cmd: $!"; |
|---|
| | 127 | }; |
|---|
| | 128 | # couldn't open file descriptors or exec failed |
|---|
| | 129 | chomp($@); my($msg) = "save_execute: $@\n"; |
|---|
| | 130 | # try to get some attention, log and stderr may be closed |
|---|
| | 131 | POSIX::write(2,$msg,length($msg)); print STDERR $msg; |
|---|
| | 132 | POSIX::_exit(8); # must avoid END and destructor processing! |
|---|
| 114 | | open(STDERR, $stderr); |
|---|
| 115 | | } |
|---|
| 116 | | exec($cmd) and exit($?); |
|---|
| 117 | | exit(-2); |
|---|
| | 170 | open_on_specific_fd(2, $stderr); |
|---|
| | 171 | } |
|---|
| | 172 | exec($cmd); |
|---|
| | 173 | die "failed to exec $cmd: $!"; |
|---|
| | 174 | }; |
|---|
| | 175 | # couldn't open file descriptors or exec failed |
|---|
| | 176 | chomp($@); my($msg) = "save_execute: $@\n"; |
|---|
| | 177 | # try to get some attention, log and stderr may be closed |
|---|
| | 178 | POSIX::write(2,$msg,length($msg)); print STDERR $msg; |
|---|
| | 179 | POSIX::_exit(8); # must avoid END and destructor processing! |
|---|
| 119 | | set_pid($pid); wait(); $retcode = $?>>8; |
|---|
| 120 | | debuglog("Elapsed: ". |
|---|
| 121 | | sprintf ("%.6f",tv_interval($begin, [gettimeofday])) |
|---|
| 122 | | ." sec. ($pgm)($retcode)"); |
|---|
| | 181 | set_pid($pid); wait(); $retcode = $?; |
|---|
| | 182 | debuglog(sprintf("Elapsed [%s]: %.6f sec. (%s: %s)", |
|---|
| | 183 | $pid, tv_interval($begin, [gettimeofday]), |
|---|
| | 184 | $pgm, exit_status_str($retcode))); |
|---|