aboutsummaryrefslogtreecommitdiff
path: root/coreutils/timeout.c
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2021-12-27 08:21:55 +0000
committerRon Yorston <rmy@pobox.com>2021-12-27 08:21:55 +0000
commitb15f68214da209b5b293039c09c00f490c0cc193 (patch)
treed644b5d9318b79cb1baa356cbb63318cc4872c05 /coreutils/timeout.c
parent1ee308c75f4720ee38be8e81ff8c9ed4c52670d4 (diff)
parent44075929a8b9c1861d15564fa6ac4562abb724d7 (diff)
downloadbusybox-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.c84
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 */
61static 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
77static 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
60int timeout_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 93int 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;