>From de2397fece839ce90f71e0624f5435755ad9ea01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81ngel=20Gonz=C3=A1lez?= Date: Mon, 29 Oct 2012 00:36:08 +0000 Subject: [PATCH] timeout: add --preserve-status to always propagate the 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 (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 | 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..767a31e 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 address@hidden --preserve-status address@hidden --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 diff --git a/src/timeout.c b/src/timeout.c index 4ce18ad..02d21c5 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 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; diff --git a/tests/misc/timeout.sh b/tests/misc/timeout.sh index 57a4e15..66d6956 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 --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. -- 1.7.6.4