diff options
author | Ron Yorston <rmy@pobox.com> | 2021-12-27 08:21:55 +0000 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2021-12-27 08:21:55 +0000 |
commit | b15f68214da209b5b293039c09c00f490c0cc193 (patch) | |
tree | d644b5d9318b79cb1baa356cbb63318cc4872c05 /coreutils/timeout.c | |
parent | 1ee308c75f4720ee38be8e81ff8c9ed4c52670d4 (diff) | |
parent | 44075929a8b9c1861d15564fa6ac4562abb724d7 (diff) | |
download | busybox-w32-b15f68214da209b5b293039c09c00f490c0cc193.tar.gz busybox-w32-b15f68214da209b5b293039c09c00f490c0cc193.tar.bz2 busybox-w32-b15f68214da209b5b293039c09c00f490c0cc193.zip |
Merge busybox into merge
Fix merge conflict in coreutils/timeout.c.
Diffstat (limited to 'coreutils/timeout.c')
-rw-r--r-- | coreutils/timeout.c | 84 |
1 files changed, 60 insertions, 24 deletions
diff --git a/coreutils/timeout.c b/coreutils/timeout.c index b161f4e91..74df31d10 100644 --- a/coreutils/timeout.c +++ b/coreutils/timeout.c | |||
@@ -39,10 +39,11 @@ | |||
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.\n" |
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 | ||
@@ -55,6 +56,38 @@ static void kill_child(void) | |||
55 | kill_SIGTERM_by_handle(child); | 56 | kill_SIGTERM_by_handle(child); |
56 | } | 57 | } |
57 | } | 58 | } |
59 | |||
60 | /* Return TRUE if child exits before timeout expires */ | ||
61 | static NOINLINE int timeout_wait(int timeout, HANDLE proc, DWORD *status) | ||
62 | { | ||
63 | /* Just sleep(HUGE_NUM); kill(parent) may kill wrong process! */ | ||
64 | while (1) { | ||
65 | sleep1(); | ||
66 | if (--timeout <= 0) | ||
67 | break; | ||
68 | if (WaitForSingleObject(proc, 0) == WAIT_OBJECT_0) { | ||
69 | /* process is gone */ | ||
70 | GetExitCodeProcess(proc, status); | ||
71 | return TRUE; | ||
72 | } | ||
73 | } | ||
74 | return FALSE; | ||
75 | } | ||
76 | #else | ||
77 | static NOINLINE int timeout_wait(int timeout, pid_t pid) | ||
78 | { | ||
79 | /* Just sleep(HUGE_NUM); kill(parent) may kill wrong process! */ | ||
80 | while (1) { | ||
81 | sleep1(); | ||
82 | if (--timeout <= 0) | ||
83 | break; | ||
84 | if (kill(pid, 0)) { | ||
85 | /* process is gone */ | ||
86 | return EXIT_SUCCESS; | ||
87 | } | ||
88 | } | ||
89 | return EXIT_FAILURE; | ||
90 | } | ||
58 | #endif | 91 | #endif |
59 | 92 | ||
60 | int timeout_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 93 | int timeout_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
@@ -69,11 +102,13 @@ int timeout_main(int argc UNUSED_PARAM, char **argv) | |||
69 | #endif | 102 | #endif |
70 | int parent = 0; | 103 | int parent = 0; |
71 | int timeout; | 104 | int timeout; |
105 | int kill_timeout; | ||
72 | pid_t pid; | 106 | pid_t pid; |
73 | #if !BB_MMU | 107 | #if !BB_MMU |
74 | char *sv1, *sv2; | 108 | char *sv1, *sv2; |
75 | #endif | 109 | #endif |
76 | const char *opt_s = "TERM"; | 110 | const char *opt_s = "TERM"; |
111 | char *opt_k = NULL; | ||
77 | 112 | ||
78 | #if ENABLE_PLATFORM_MINGW32 | 113 | #if ENABLE_PLATFORM_MINGW32 |
79 | xfunc_error_retval = 125; | 114 | xfunc_error_retval = 125; |
@@ -83,7 +118,7 @@ int timeout_main(int argc UNUSED_PARAM, char **argv) | |||
83 | 118 | ||
84 | /* -t SECONDS; -p PARENT_PID */ | 119 | /* -t SECONDS; -p PARENT_PID */ |
85 | /* '+': stop at first non-option */ | 120 | /* '+': stop at first non-option */ |
86 | getopt32(argv, "+s:" USE_FOR_NOMMU("p:+"), &opt_s, &parent); | 121 | getopt32(argv, "+s:k:" USE_FOR_NOMMU("p:+"), &opt_s, &opt_k, &parent); |
87 | /*argv += optind; - no, wait for bb_daemonize_or_rexec! */ | 122 | /*argv += optind; - no, wait for bb_daemonize_or_rexec! */ |
88 | 123 | ||
89 | signo = get_signum(opt_s); | 124 | signo = get_signum(opt_s); |
@@ -94,6 +129,10 @@ int timeout_main(int argc UNUSED_PARAM, char **argv) | |||
94 | #endif | 129 | #endif |
95 | bb_error_msg_and_die("unknown signal '%s'", opt_s); | 130 | bb_error_msg_and_die("unknown signal '%s'", opt_s); |
96 | 131 | ||
132 | kill_timeout = 0; | ||
133 | if (opt_k) | ||
134 | kill_timeout = parse_duration_str(opt_k); | ||
135 | |||
97 | if (!argv[optind]) | 136 | if (!argv[optind]) |
98 | bb_show_usage(); | 137 | bb_show_usage(); |
99 | timeout = parse_duration_str(argv[optind++]); | 138 | timeout = parse_duration_str(argv[optind++]); |
@@ -128,17 +167,16 @@ int timeout_main(int argc UNUSED_PARAM, char **argv) | |||
128 | bb_daemonize_or_rexec(0, argv); | 167 | bb_daemonize_or_rexec(0, argv); |
129 | /* Here we are grandchild. Sleep, then kill grandparent */ | 168 | /* Here we are grandchild. Sleep, then kill grandparent */ |
130 | grandchild: | 169 | grandchild: |
131 | /* Just sleep(HUGE_NUM); kill(parent) may kill wrong process! */ | 170 | if (timeout_wait(timeout, parent) == EXIT_SUCCESS) |
132 | while (1) { | 171 | return EXIT_SUCCESS; |
133 | sleep1(); | 172 | kill(parent, signo); |
134 | if (--timeout <= 0) | 173 | |
135 | break; | 174 | if (kill_timeout > 0) { |
136 | if (kill(parent, 0)) { | 175 | if (timeout_wait(kill_timeout, parent) == EXIT_SUCCESS) |
137 | /* process is gone */ | ||
138 | return EXIT_SUCCESS; | 176 | return EXIT_SUCCESS; |
139 | } | 177 | kill(parent, SIGKILL); |
140 | } | 178 | } |
141 | kill(parent, signo); | 179 | |
142 | return EXIT_SUCCESS; | 180 | return EXIT_SUCCESS; |
143 | } | 181 | } |
144 | 182 | ||
@@ -163,21 +201,19 @@ int timeout_main(int argc UNUSED_PARAM, char **argv) | |||
163 | 201 | ||
164 | child = (HANDLE)ret; | 202 | child = (HANDLE)ret; |
165 | atexit(kill_child); | 203 | atexit(kill_child); |
166 | while (1) { | 204 | if (timeout_wait(timeout, child, &status)) |
167 | sleep(1); | 205 | goto finish; |
168 | if (signo && --timeout <= 0) { | 206 | status = signo == SIGKILL ? 137 : 124; |
169 | status = signo == SIGKILL ? 137 : 124; | ||
170 | break; | ||
171 | } | ||
172 | if (WaitForSingleObject(child, 0) == WAIT_OBJECT_0) { | ||
173 | /* process is gone */ | ||
174 | GetExitCodeProcess(child, &status); | ||
175 | goto finish; | ||
176 | } | ||
177 | } | ||
178 | 207 | ||
179 | pid = (pid_t)GetProcessId(child); | 208 | pid = (pid_t)GetProcessId(child); |
180 | kill(pid, signo); | 209 | kill(pid, signo); |
210 | |||
211 | if (kill_timeout > 0) { | ||
212 | if (timeout_wait(kill_timeout, child, &status)) | ||
213 | goto finish; | ||
214 | kill(parent, SIGKILL); | ||
215 | status = 137; | ||
216 | } | ||
181 | finish: | 217 | finish: |
182 | CloseHandle(child); | 218 | CloseHandle(child); |
183 | child = INVALID_HANDLE_VALUE; | 219 | child = INVALID_HANDLE_VALUE; |