From: Pádraig Brady
Date: Thu, 23 Nov 2017 22:30:59 +0000 (-0800) Subject: timeout: add --verbose to diagnose timeouts X-Git-Tag: v8.29~29 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=559c7a57c73d619bbf68b2f6176bed0801d9716c;p=thirdparty%2Fcoreutils.git timeout: add --verbose to diagnose timeouts This is useful as handling in shell is complicated with the varying exit status in the --kill-after case. * src/timeout.c (main): Handle '-v' and store COMMAND for the diagnostic. (cleanup): Diagnose the signal name before sending. (usage): Document -v, --verbose. * doc/coreutils.texi (timeout invocation): Likewise. * tests/misc/timeout.sh: Add a test case. * NEWS: Mention the new feature Fixes https://bugs.gnu.org/21760 --- diff --git a/NEWS b/NEWS index bc5d5beeb7..4c697b591e 100644 --- a/NEWS +++ b/NEWS @@ -31,6 +31,10 @@ GNU coreutils NEWS -*- outline -*- timeout would have then waited for the time limit to expire. [bug introduced in coreutils-8.27] +** New features + + timeout now supports the --verbose option to diagnose forced termination. + ** Improvements tail --bytes=NUM will efficiently seek to the end of block devices, diff --git a/doc/coreutils.texi b/doc/coreutils.texi index d374b4abcd..98ea4e228f 100644 --- a/doc/coreutils.texi +++ b/doc/coreutils.texi @@ -17388,6 +17388,12 @@ the @var{command}. Send this @var{signal} to @var{command} on timeout, rather than the default @samp{TERM} signal. @var{signal} may be a name like @samp{HUP} or a number. @xref{Signal specifications}. + +@item -v +@itemx --verbose +@opindex -v +@opindex --verbose +Diagnose to stderr, any signal sent upon timeout. @end table @cindex time units diff --git a/src/timeout.c b/src/timeout.c index 562781943e..466ada2efb 100644 --- a/src/timeout.c +++ b/src/timeout.c @@ -83,6 +83,8 @@ static pid_t monitored_pid; static double kill_after; static bool foreground; /* whether to use another program group. */ static bool preserve_status; /* whether to use a timeout status or not. */ +static bool verbose; /* whether to diagnose timeouts or not. */ +static char const* command; /* for long options with no corresponding short option, use enum */ enum @@ -95,6 +97,7 @@ static struct option const long_options[] = { {"kill-after", required_argument, NULL, 'k'}, {"signal", required_argument, NULL, 's'}, + {"verbose", no_argument, NULL, 'v'}, {"foreground", no_argument, NULL, FOREGROUND_OPTION}, {"preserve-status", no_argument, NULL, PRESERVE_STATUS_OPTION}, {GETOPT_HELP_OPTION_DECL}, @@ -196,6 +199,14 @@ cleanup (int sig) /* Send the signal directly to the monitored child, in case it has itself become group leader, or is not running in a separate group. */ + if (verbose) + { + char signame[MAX (SIG2STR_MAX, INT_BUFSIZE_BOUND (int))]; + if (sig2str (sig, signame) != 0) + snprintf (signame, sizeof signame, "%d", sig); + error (0, 0, _("sending signal %s to command %s"), + signame, quote (command)); + } send_sig (monitored_pid, sig); /* The normal case is the job has remained in our @@ -246,6 +257,8 @@ Start COMMAND, and kill it if still running after DURATION.\n\ specify the signal to be sent on timeout;\n\ SIGNAL may be a name like 'HUP' or a number;\n\ see 'kill -l' for a list of signals\n"), stdout); + fputs (_("\ + -v, --verbose diagnose to stderr any signal sent upon timeout\n"), stdout); fputs (HELP_OPTION_DESCRIPTION, stdout); fputs (VERSION_OPTION_DESCRIPTION, stdout); @@ -443,6 +456,10 @@ main (int argc, char **argv) usage (EXIT_CANCELED); break; + case 'v': + verbose = true; + break; + case FOREGROUND_OPTION: foreground = true; break; @@ -467,6 +484,7 @@ main (int argc, char **argv) timeout = parse_duration (argv[optind++]); argv += optind; + command = argv[0]; /* Ensure we're in our own group so all subprocesses can be killed. Note we don't just put the child in a separate group as @@ -498,7 +516,7 @@ main (int argc, char **argv) /* exit like sh, env, nohup, ... */ int exit_status = errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE; - error (0, errno, _("failed to run command %s"), quote (argv[0])); + error (0, errno, _("failed to run command %s"), quote (command)); return exit_status; } else diff --git a/tests/misc/timeout.sh b/tests/misc/timeout.sh index 1c765896af..a4a55b615b 100755 --- a/tests/misc/timeout.sh +++ b/tests/misc/timeout.sh @@ -57,4 +57,12 @@ out=$(sleep .1 & exec timeout .5 sh -c 'sleep 2; echo foo') status=$? test "$out" = "" && test $status = 124 || fail=1 +# Verify --verbose output +timeout --verbose -s0 -k .1 .1 sleep 10 2> err +cat > exp <<\EOF +timeout: sending signal EXIT to command 'sleep' +timeout: sending signal KILL to command 'sleep' +EOF +compare exp err || fail=1 + Exit $fail