On 10/22/2012 01:27 PM, Thomas Krennwallner wrote:
On Mon Oct 22, 2012 10:20:14AM +0100, Pádraig Brady wrote:
On 10/21/2012 09:36 PM, Thomas Krennwallner wrote:
[...]
I'm thus very interested into seeing timeout --exit-status.

Ok cool.

It's tempting to support this without an option.
I.E. for all commands that exit without WIFSIGNALED being set,
i.e. for all commands that catch and exit on signal reception.
However that wouldn't work in general I think due to cascading
timeout commands or commands that catch signals for cleanup etc.,
though I suppose the latter case might be catered for by
specifying a specific signal with the -s option.

Yes, I completely agree.  And would only make a difference for programs
that carry on meaning with their exit code, i.e., where the code depends
on the computation, as described in my use case.  The default use is
IMHO just error exit in programs, and most have it implemented this way
(think of clean-up at signal reception).  Having a default exit code of
124 is good for those standard programs.

So I'll look at adding this new option right after the
imminent 8.20 release.

Thank you, this sounds like good news!

Proposed patch is attached.

thanks,
Pádraig.
>From 0c5f991abe9875741d1812f5be91c249d9418b17 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=81ngel=20Gonz=C3=A1lez?= <keis...@gmail.com>
Date: Mon, 29 Oct 2012 00:36:08 +0000
Subject: [PATCH] timeout: add --exit-status to always propagate the command's
 exit status

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 (use_exit_status): A new global boolean to
enable the --exit-status behavior.
(usage): Describe the new option.
(main): Don't return EXIT_TIMEOUT of use_exit_status is set.
* tests/misc/timeout.sh: Add a test for the new option.
---
 doc/coreutils.texi    |    6 ++++++
 src/timeout.c         |   28 +++++++++++++++++++---------
 tests/misc/timeout.sh |    5 +++++
 3 files changed, 30 insertions(+), 9 deletions(-)

diff --git a/doc/coreutils.texi b/doc/coreutils.texi
index e2b1059..6e047c5 100644
--- a/doc/coreutils.texi
+++ b/doc/coreutils.texi
@@ -15890,6 +15890,12 @@ The program accepts the following options.  Also see @ref{Common options}.
 Options must precede operands.
 
 @table @samp
+@item --exit-status
+@opindex --exit-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
diff --git a/src/timeout.c b/src/timeout.c
index 4ce18ad..3f90ac7 100644
--- a/src/timeout.c
+++ b/src/timeout.c
@@ -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 use_exit_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,
+      EXIT_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},
+  {"exit-status", no_argument, NULL, EXIT_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 (_("\
+      --exit-status\n\
+                 exit with the same status as COMMAND even if the\n\
+                 command timed 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 --exit-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 EXIT_STATUS_OPTION:
+          use_exit_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 && !use_exit_status)
         return EXIT_TIMEDOUT;
       else
         return status;
diff --git a/tests/misc/timeout.sh b/tests/misc/timeout.sh
index 57a4e15..3fa8522 100755
--- a/tests/misc/timeout.sh
+++ b/tests/misc/timeout.sh
@@ -36,6 +36,11 @@ test $? = 2 || fail=1
 timeout 1 sleep 10
 test $? = 124 || fail=1
 
+# exit status propagation even on timeout
+timeout --exit-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.
-- 
1.7.6.4

Reply via email to