diff options
author | Ron Yorston <rmy@pobox.com> | 2023-04-07 12:52:57 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2023-04-07 12:52:57 +0100 |
commit | 99402ca92c77b13bee5181c129db18ecd9bf8938 (patch) | |
tree | a534d31940f305f13c17d849dce9f38418533d5f | |
parent | 9db9b34adaad1a9ebe892eaea486cfe0610bad8d (diff) | |
download | busybox-w32-99402ca92c77b13bee5181c129db18ecd9bf8938.tar.gz busybox-w32-99402ca92c77b13bee5181c129db18ecd9bf8938.tar.bz2 busybox-w32-99402ca92c77b13bee5181c129db18ecd9bf8938.zip |
xargs: kill children when interrupted by Ctrl-C
A user was running the following command in a clone of the
busybox-w32 repo from a busybox-w32 shell using Git for Windows:
git rev-list --all | xargs git grep main.c
Using Ctrl-C to interrupt the command resulted in the familiar
problem that two processes ended up competing for user input:
in this case the busybox-w32 shell and the Git for Windows pager,
less.
Make the problem go away (in this particular case) by killing all
the children of xargs when it's interrupted. This is probably a
sensible thing to do for other circumstances too.
Adds 64-100 bytes.
(GitHub issue #306)
-rw-r--r-- | findutils/xargs.c | 45 |
1 files changed, 42 insertions, 3 deletions
diff --git a/findutils/xargs.c b/findutils/xargs.c index d6cdec22e..1023f80a3 100644 --- a/findutils/xargs.c +++ b/findutils/xargs.c | |||
@@ -121,9 +121,12 @@ struct globals { | |||
121 | #if ENABLE_FEATURE_XARGS_SUPPORT_PARALLEL | 121 | #if ENABLE_FEATURE_XARGS_SUPPORT_PARALLEL |
122 | int running_procs; | 122 | int running_procs; |
123 | int max_procs; | 123 | int max_procs; |
124 | #if ENABLE_PLATFORM_MINGW32 | 124 | # if ENABLE_PLATFORM_MINGW32 |
125 | HANDLE *procs; | 125 | HANDLE *procs; |
126 | # endif | ||
126 | #endif | 127 | #endif |
128 | #if ENABLE_PLATFORM_MINGW32 | ||
129 | pid_t pid; | ||
127 | #endif | 130 | #endif |
128 | smalluint xargs_exitcode; | 131 | smalluint xargs_exitcode; |
129 | #if ENABLE_FEATURE_XARGS_SUPPORT_QUOTES | 132 | #if ENABLE_FEATURE_XARGS_SUPPORT_QUOTES |
@@ -189,6 +192,35 @@ enum { | |||
189 | IF_FEATURE_XARGS_SUPPORT_ARGS_FILE( "a:") | 192 | IF_FEATURE_XARGS_SUPPORT_ARGS_FILE( "a:") |
190 | 193 | ||
191 | 194 | ||
195 | #if ENABLE_PLATFORM_MINGW32 | ||
196 | static BOOL WINAPI ctrl_handler(DWORD dwCtrlType) | ||
197 | { | ||
198 | if (dwCtrlType == CTRL_C_EVENT || dwCtrlType == CTRL_BREAK_EVENT) { | ||
199 | # if ENABLE_FEATURE_XARGS_SUPPORT_PARALLEL | ||
200 | if (G.max_procs == 1) | ||
201 | # endif | ||
202 | { | ||
203 | if (G.pid > 0) | ||
204 | kill(-G.pid, SIGTERM); | ||
205 | } | ||
206 | # if ENABLE_FEATURE_XARGS_SUPPORT_PARALLEL | ||
207 | else { | ||
208 | int i; | ||
209 | |||
210 | for (i = 0; i < G.running_procs; ++i) { | ||
211 | pid_t pid = GetProcessId(G.procs[i]); | ||
212 | if (pid > 0) | ||
213 | kill(-pid, SIGTERM); | ||
214 | } | ||
215 | } | ||
216 | # endif | ||
217 | exit(128 + SIGINT); | ||
218 | return TRUE; | ||
219 | } | ||
220 | return FALSE; | ||
221 | } | ||
222 | #endif | ||
223 | |||
192 | #if ENABLE_FEATURE_XARGS_SUPPORT_PARALLEL && ENABLE_PLATFORM_MINGW32 | 224 | #if ENABLE_FEATURE_XARGS_SUPPORT_PARALLEL && ENABLE_PLATFORM_MINGW32 |
193 | static int wait_for_slot(int *idx) | 225 | static int wait_for_slot(int *idx) |
194 | { | 226 | { |
@@ -255,10 +287,11 @@ static int xargs_exec(void) | |||
255 | #if !ENABLE_FEATURE_XARGS_SUPPORT_PARALLEL | 287 | #if !ENABLE_FEATURE_XARGS_SUPPORT_PARALLEL |
256 | status = spawn_and_wait(G.args); | 288 | status = spawn_and_wait(G.args); |
257 | #else | 289 | #else |
290 | #if ENABLE_PLATFORM_MINGW32 | ||
258 | if (G.max_procs == 1) { | 291 | if (G.max_procs == 1) { |
259 | status = spawn_and_wait(G.args); | 292 | G.pid = spawn(G.args); |
293 | status = G.pid < 0 ? -1 : wait4pid(G.pid); | ||
260 | } else { | 294 | } else { |
261 | #if ENABLE_PLATFORM_MINGW32 | ||
262 | int idx; | 295 | int idx; |
263 | status = !G.running_procs && !G.max_procs ? 0 : wait_for_slot(&idx); | 296 | status = !G.running_procs && !G.max_procs ? 0 : wait_for_slot(&idx); |
264 | if (G.max_procs) { | 297 | if (G.max_procs) { |
@@ -275,6 +308,9 @@ static int xargs_exec(void) | |||
275 | } | 308 | } |
276 | } | 309 | } |
277 | #else | 310 | #else |
311 | if (G.max_procs == 1) { | ||
312 | status = spawn_and_wait(G.args); | ||
313 | } else { | ||
278 | pid_t pid; | 314 | pid_t pid; |
279 | int wstat; | 315 | int wstat; |
280 | again: | 316 | again: |
@@ -723,6 +759,9 @@ int xargs_main(int argc UNUSED_PARAM, char **argv) | |||
723 | 759 | ||
724 | INIT_G(); | 760 | INIT_G(); |
725 | 761 | ||
762 | #if ENABLE_PLATFORM_MINGW32 | ||
763 | SetConsoleCtrlHandler(ctrl_handler, TRUE); | ||
764 | #endif | ||
726 | opt = getopt32long(argv, OPTION_STR, | 765 | opt = getopt32long(argv, OPTION_STR, |
727 | "no-run-if-empty\0" No_argument "r", | 766 | "no-run-if-empty\0" No_argument "r", |
728 | &max_args, &max_chars, &G.eof_str, &G.eof_str | 767 | &max_args, &max_chars, &G.eof_str, &G.eof_str |