diff options
author | Matthew Slowe <foo@mafoo.org.uk> | 2021-10-09 14:26:40 +0300 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2021-12-18 01:11:17 +0300 |
commit | 7d49fedc86bec300d22f44f93ec95825320dd1c1 (patch) | |
tree | 0bb535177a75500ebc5ecef1a2d07b7c023d838f /coreutils | |
parent | c1eac153e8b89cfc9d550991735c09bad1579201 (diff) |
timeout: add support for "timeout -k KILL_SECS"
function old new delta
timeout_main 307 373 +66
timeout_wait - 42 +42
.rodata 104201 104203 +2
packed_usage 34097 34096 -1
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 2/1 up/down: 110/-1) Total: 109 bytes
Signed-off-by: Matthew Slowe <foo@mafoo.org.uk>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'coreutils')
-rw-r--r-- | coreutils/timeout.c | 43 |
1 files changed, 32 insertions, 11 deletions
diff --git a/coreutils/timeout.c b/coreutils/timeout.c index 8485e1e7d..06108f315 100644 --- a/coreutils/timeout.c +++ b/coreutils/timeout.c @@ -39,13 +39,29 @@ //kbuild:lib-$(CONFIG_TIMEOUT) += timeout.o //usage:#define timeout_trivial_usage -//usage: "[-s SIG] SECS PROG ARGS" +//usage: "[-s SIG] [-k KILL_SECS] SECS PROG ARGS" //usage:#define timeout_full_usage "\n\n" //usage: "Run PROG. Send SIG to it if it is not gone in SECS seconds.\n" //usage: "Default SIG: TERM." +//usage: "If it still exists in KILL_SECS seconds, send KILL.\n" #include "libbb.h" +static NOINLINE int timeout_wait(int timeout, pid_t pid) +{ + /* Just sleep(HUGE_NUM); kill(parent) may kill wrong process! */ + while (1) { + sleep1(); + if (--timeout <= 0) + break; + if (kill(pid, 0)) { + /* process is gone */ + return EXIT_SUCCESS; + } + } + return EXIT_FAILURE; +} + int timeout_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int timeout_main(int argc UNUSED_PARAM, char **argv) { @@ -53,23 +69,29 @@ int timeout_main(int argc UNUSED_PARAM, char **argv) int status; int parent = 0; int timeout; + int kill_timeout; pid_t pid; #if !BB_MMU char *sv1, *sv2; #endif const char *opt_s = "TERM"; + char *opt_k = NULL; /* -p option is not documented, it is needed to support NOMMU. */ /* -t SECONDS; -p PARENT_PID */ /* '+': stop at first non-option */ - getopt32(argv, "+s:" USE_FOR_NOMMU("p:+"), &opt_s, &parent); + getopt32(argv, "+s:k:" USE_FOR_NOMMU("p:+"), &opt_s, &opt_k, &parent); /*argv += optind; - no, wait for bb_daemonize_or_rexec! */ signo = get_signum(opt_s); if (signo < 0) bb_error_msg_and_die("unknown signal '%s'", opt_s); + kill_timeout = 0; + if (opt_k) + kill_timeout = parse_duration_str(opt_k); + if (!argv[optind]) bb_show_usage(); timeout = parse_duration_str(argv[optind++]); @@ -103,17 +125,16 @@ int timeout_main(int argc UNUSED_PARAM, char **argv) bb_daemonize_or_rexec(0, argv); /* Here we are grandchild. Sleep, then kill grandparent */ grandchild: - /* Just sleep(HUGE_NUM); kill(parent) may kill wrong process! */ - while (1) { - sleep1(); - if (--timeout <= 0) - break; - if (kill(parent, 0)) { - /* process is gone */ + if (timeout_wait(timeout, parent) == EXIT_SUCCESS) + return EXIT_SUCCESS; + kill(parent, signo); + + if (kill_timeout > 0) { + if (timeout_wait(kill_timeout, parent) == EXIT_SUCCESS) return EXIT_SUCCESS; - } + kill(parent, SIGKILL); } - kill(parent, signo); + return EXIT_SUCCESS; } |