diff options
author | Matthew Slowe <foo@mafoo.org.uk> | 2021-10-09 12:26:40 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2021-12-17 23:11:17 +0100 |
commit | 7d49fedc86bec300d22f44f93ec95825320dd1c1 (patch) | |
tree | 0bb535177a75500ebc5ecef1a2d07b7c023d838f | |
parent | c1eac153e8b89cfc9d550991735c09bad1579201 (diff) | |
download | busybox-w32-7d49fedc86bec300d22f44f93ec95825320dd1c1.tar.gz busybox-w32-7d49fedc86bec300d22f44f93ec95825320dd1c1.tar.bz2 busybox-w32-7d49fedc86bec300d22f44f93ec95825320dd1c1.zip |
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>
-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 @@ | |||
39 | //kbuild:lib-$(CONFIG_TIMEOUT) += timeout.o | 39 | //kbuild:lib-$(CONFIG_TIMEOUT) += timeout.o |
40 | 40 | ||
41 | //usage:#define timeout_trivial_usage | 41 | //usage:#define timeout_trivial_usage |
42 | //usage: "[-s SIG] SECS PROG ARGS" | 42 | //usage: "[-s SIG] [-k KILL_SECS] SECS PROG ARGS" |
43 | //usage:#define timeout_full_usage "\n\n" | 43 | //usage:#define timeout_full_usage "\n\n" |
44 | //usage: "Run PROG. Send SIG to it if it is not gone in SECS seconds.\n" | 44 | //usage: "Run PROG. Send SIG to it if it is not gone in SECS seconds.\n" |
45 | //usage: "Default SIG: TERM." | 45 | //usage: "Default SIG: TERM." |
46 | //usage: "If it still exists in KILL_SECS seconds, send KILL.\n" | ||
46 | 47 | ||
47 | #include "libbb.h" | 48 | #include "libbb.h" |
48 | 49 | ||
50 | static NOINLINE int timeout_wait(int timeout, pid_t pid) | ||
51 | { | ||
52 | /* Just sleep(HUGE_NUM); kill(parent) may kill wrong process! */ | ||
53 | while (1) { | ||
54 | sleep1(); | ||
55 | if (--timeout <= 0) | ||
56 | break; | ||
57 | if (kill(pid, 0)) { | ||
58 | /* process is gone */ | ||
59 | return EXIT_SUCCESS; | ||
60 | } | ||
61 | } | ||
62 | return EXIT_FAILURE; | ||
63 | } | ||
64 | |||
49 | int timeout_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 65 | int timeout_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
50 | int timeout_main(int argc UNUSED_PARAM, char **argv) | 66 | int timeout_main(int argc UNUSED_PARAM, char **argv) |
51 | { | 67 | { |
@@ -53,23 +69,29 @@ int timeout_main(int argc UNUSED_PARAM, char **argv) | |||
53 | int status; | 69 | int status; |
54 | int parent = 0; | 70 | int parent = 0; |
55 | int timeout; | 71 | int timeout; |
72 | int kill_timeout; | ||
56 | pid_t pid; | 73 | pid_t pid; |
57 | #if !BB_MMU | 74 | #if !BB_MMU |
58 | char *sv1, *sv2; | 75 | char *sv1, *sv2; |
59 | #endif | 76 | #endif |
60 | const char *opt_s = "TERM"; | 77 | const char *opt_s = "TERM"; |
78 | char *opt_k = NULL; | ||
61 | 79 | ||
62 | /* -p option is not documented, it is needed to support NOMMU. */ | 80 | /* -p option is not documented, it is needed to support NOMMU. */ |
63 | 81 | ||
64 | /* -t SECONDS; -p PARENT_PID */ | 82 | /* -t SECONDS; -p PARENT_PID */ |
65 | /* '+': stop at first non-option */ | 83 | /* '+': stop at first non-option */ |
66 | getopt32(argv, "+s:" USE_FOR_NOMMU("p:+"), &opt_s, &parent); | 84 | getopt32(argv, "+s:k:" USE_FOR_NOMMU("p:+"), &opt_s, &opt_k, &parent); |
67 | /*argv += optind; - no, wait for bb_daemonize_or_rexec! */ | 85 | /*argv += optind; - no, wait for bb_daemonize_or_rexec! */ |
68 | 86 | ||
69 | signo = get_signum(opt_s); | 87 | signo = get_signum(opt_s); |
70 | if (signo < 0) | 88 | if (signo < 0) |
71 | bb_error_msg_and_die("unknown signal '%s'", opt_s); | 89 | bb_error_msg_and_die("unknown signal '%s'", opt_s); |
72 | 90 | ||
91 | kill_timeout = 0; | ||
92 | if (opt_k) | ||
93 | kill_timeout = parse_duration_str(opt_k); | ||
94 | |||
73 | if (!argv[optind]) | 95 | if (!argv[optind]) |
74 | bb_show_usage(); | 96 | bb_show_usage(); |
75 | timeout = parse_duration_str(argv[optind++]); | 97 | timeout = parse_duration_str(argv[optind++]); |
@@ -103,17 +125,16 @@ int timeout_main(int argc UNUSED_PARAM, char **argv) | |||
103 | bb_daemonize_or_rexec(0, argv); | 125 | bb_daemonize_or_rexec(0, argv); |
104 | /* Here we are grandchild. Sleep, then kill grandparent */ | 126 | /* Here we are grandchild. Sleep, then kill grandparent */ |
105 | grandchild: | 127 | grandchild: |
106 | /* Just sleep(HUGE_NUM); kill(parent) may kill wrong process! */ | 128 | if (timeout_wait(timeout, parent) == EXIT_SUCCESS) |
107 | while (1) { | 129 | return EXIT_SUCCESS; |
108 | sleep1(); | 130 | kill(parent, signo); |
109 | if (--timeout <= 0) | 131 | |
110 | break; | 132 | if (kill_timeout > 0) { |
111 | if (kill(parent, 0)) { | 133 | if (timeout_wait(kill_timeout, parent) == EXIT_SUCCESS) |
112 | /* process is gone */ | ||
113 | return EXIT_SUCCESS; | 134 | return EXIT_SUCCESS; |
114 | } | 135 | kill(parent, SIGKILL); |
115 | } | 136 | } |
116 | kill(parent, signo); | 137 | |
117 | return EXIT_SUCCESS; | 138 | return EXIT_SUCCESS; |
118 | } | 139 | } |
119 | 140 | ||