aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2023-04-07 12:52:57 +0100
committerRon Yorston <rmy@pobox.com>2023-04-07 12:52:57 +0100
commit99402ca92c77b13bee5181c129db18ecd9bf8938 (patch)
treea534d31940f305f13c17d849dce9f38418533d5f
parent9db9b34adaad1a9ebe892eaea486cfe0610bad8d (diff)
downloadbusybox-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.c45
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
196static 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
193static int wait_for_slot(int *idx) 225static 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