]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
timeout: add --preserve-status to always propagate the exit status
authorÁngel González <keisial@gmail.com>
Mon, 29 Oct 2012 00:36:08 +0000 (00:36 +0000)
committerPádraig Brady <P@draigBrady.com>
Sun, 4 Nov 2012 01:48:14 +0000 (01:48 +0000)
It's useful for commands that support running for an indeterminite
amount of time, to not return a specific timeout exit status (124),
and instead let the command handle the timeout signal and return
a status for the work done so far.

* doc/coreutils.texi (timeout invocation): Describe the new option.
* src/timeout.c (preserve_status): A new global boolean to
enable the --preserve-status behavior.
(usage): Describe the new option.
(main): Don't return EXIT_TIMEOUT of preserve_status is set.
* tests/misc/timeout.sh: Add a test for the new option.

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

index e2b105912970ff32f26e50bcdc06d323a18d524d..767a31e9c6057132c6e9c1b9ea37f394cbfe3f92 100644 (file)
@@ -15890,6 +15890,12 @@ The program accepts the following options.  Also see @ref{Common options}.
 Options must precede operands.
 
 @table @samp
+@item --preserve-status
+@opindex --preserve-status
+Return the exit status of the managed @var{command} on timeout, rather than
+a specific exit status indicating a timeout.  This is useful if the
+managed @var{command} supports running for an indeterminite amount of time.
+
 @item --foreground
 @opindex --foreground
 Don't create a separate background program group, so that
index 4ce18adc60de7867723a03bc875b9eaa1c35f4bf..02d21c56fe2f7568ee3208206535dc788757f887 100644 (file)
@@ -81,12 +81,14 @@ static int timed_out;
 static int term_signal = SIGTERM;  /* same default as kill command.  */
 static int monitored_pid;
 static double kill_after;
-static bool foreground;            /* whether to use another program group.  */
+static bool foreground;      /* whether to use another program group.  */
+static bool preserve_status; /* whether to use a timeout status or not.  */
 
 /* for long options with no corresponding short option, use enum */
 enum
 {
-      FOREGROUND_OPTION = CHAR_MAX + 1
+      FOREGROUND_OPTION = CHAR_MAX + 1,
+      PRESERVE_STATUS_OPTION
 };
 
 static struct option const long_options[] =
@@ -94,6 +96,7 @@ static struct option const long_options[] =
   {"kill-after", required_argument, NULL, 'k'},
   {"signal", required_argument, NULL, 's'},
   {"foreground", no_argument, NULL, FOREGROUND_OPTION},
+  {"preserve-status", no_argument, NULL, PRESERVE_STATUS_OPTION},
   {GETOPT_HELP_OPTION_DECL},
   {GETOPT_VERSION_OPTION_DECL},
   {NULL, 0, NULL, 0}
@@ -214,6 +217,9 @@ Start COMMAND, and kill it if still running after DURATION.\n\
 Mandatory arguments to long options are mandatory for short options too.\n\
 "), stdout);
       fputs (_("\
+      --preserve-status\n\
+                 exit with the same status as COMMAND, even when the\n\
+                 command times out\n\
       --foreground\n\
                  When not running timeout directly from a shell prompt,\n\
                  allow COMMAND to read from the TTY and receive TTY signals.\n\
@@ -235,12 +241,12 @@ DURATION is a floating point number with an optional suffix:\n\
 or 'd' for days.\n"), stdout);
 
       fputs (_("\n\
-If the command times out, then exit with status 124.  Otherwise, exit\n\
-with the status of COMMAND.  If no signal is specified, send the TERM\n\
-signal upon timeout.  The TERM signal kills any process that does not\n\
-block or catch that signal.  For other processes, it may be necessary to\n\
-use the KILL (9) signal, since this signal cannot be caught.  If the\n\
-KILL (9) signal is sent, the exit status is 128+9 rather than 124.\n"), stdout);
+If the command times out, and --preserve-status is not set, then exit with\n\
+status 124.  Otherwise, exit with the status of COMMAND.  If no signal\n\
+is specified, send the TERM signal upon timeout.  The TERM signal kills\n\
+any process that does not block or catch that signal.  It may be necessary\n\
+to use the KILL (9) signal, since this signal cannot be caught, in which\n\
+case the exit status is 128+9 rather than 124.\n"), stdout);
       emit_ancillary_info ();
     }
   exit (status);
@@ -376,6 +382,10 @@ main (int argc, char **argv)
           foreground = true;
           break;
 
+        case PRESERVE_STATUS_OPTION:
+          preserve_status = true;
+          break;
+
         case_GETOPT_HELP_CHAR;
 
         case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
@@ -470,7 +480,7 @@ main (int argc, char **argv)
             }
         }
 
-      if (timed_out)
+      if (timed_out && !preserve_status)
         return EXIT_TIMEDOUT;
       else
         return status;
index 57a4e15d0f8b0d65a96e76bf4300792a4300d522..66d69566ed0353e11fbe6287cd579c6fdce0d7bd 100755 (executable)
@@ -36,6 +36,11 @@ test $? = 2 || fail=1
 timeout 1 sleep 10
 test $? = 124 || fail=1
 
+# exit status propagation even on timeout
+timeout --preserve-status 1 sleep 10
+# exit status should be 128+TERM
+test $? = 124 && fail=1
+
 # kill delay. Note once the initial timeout triggers,
 # the exit status will be 124 even if the command
 # exits on its own accord.