]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
timeout: add --verbose to diagnose timeouts
authorPádraig Brady <P@draigBrady.com>
Thu, 23 Nov 2017 22:30:59 +0000 (14:30 -0800)
committerPádraig Brady <P@draigBrady.com>
Fri, 24 Nov 2017 01:46:55 +0000 (17:46 -0800)
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

NEWS
doc/coreutils.texi
src/timeout.c
tests/misc/timeout.sh

diff --git a/NEWS b/NEWS
index bc5d5beeb7b5334a2a222e26d43b7e2b4c541c9a..4c697b591e4baaee0b66ee92817e361f864dcc5d 100644 (file)
--- 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,
index d374b4abcd6610858c57343267eba4ff62ec3141..98ea4e228fdd86ba6193b2a362305c9d64f4784b 100644 (file)
@@ -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
index 562781943edd84c4bdd767711f6ce4a4a512c727..466ada2efb18b0e73bcb31f2edbe050e99b17afc 100644 (file)
@@ -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
index 1c765896afc19a04e151df861aa27205b5984508..a4a55b615be22f6c896224c43ac9f1da13e87ea3 100755 (executable)
@@ -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