aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2023-05-23 10:57:56 +0100
committerRon Yorston <rmy@pobox.com>2023-05-23 10:57:56 +0100
commit20b6a57af64506a4152b145b031aad2946a37ca8 (patch)
treec92e38c5e72e1b7ac36845a15967d6f4fe60c8f7
parent89aa9d783c535670c6aed1d32c8740b7474cca00 (diff)
downloadbusybox-w32-20b6a57af64506a4152b145b031aad2946a37ca8.tar.gz
busybox-w32-20b6a57af64506a4152b145b031aad2946a37ca8.tar.bz2
busybox-w32-20b6a57af64506a4152b145b031aad2946a37ca8.zip
win32: crtl-c interrupts non-console applications
Commit 9db9b34ad (win32: ignore ctrl-c in parent of execve(2)) prevented a parent process from reacting to Ctrl-C while it was waiting for its child to complete. This avoids the problem where a shell and an interactive child end up competing for input after a Ctrl-C. However, a child process which isn't attached to the console (a GUI application, for example) can't then be killed by Ctrl-C. Instead of completely ignoring Ctrl-C give the parent a handler which detects if its child is attached to the console. If so it's left to handle Ctrl-C itself and the parent ignores the interrupt. If not the parent terminates the child and all its children as if by SIGINT. Costs 200 bytes.
-rw-r--r--include/mingw.h1
-rw-r--r--win32/process.c37
2 files changed, 37 insertions, 1 deletions
diff --git a/include/mingw.h b/include/mingw.h
index f94804d91..13adf9017 100644
--- a/include/mingw.h
+++ b/include/mingw.h
@@ -540,6 +540,7 @@ int mingw_execve(const char *cmd, char *const *argv, char *const *envp);
540 540
541#define has_dos_drive_prefix(path) (isalpha(*(path)) && (path)[1] == ':') 541#define has_dos_drive_prefix(path) (isalpha(*(path)) && (path)[1] == ':')
542 542
543BOOL WINAPI kill_child_ctrl_handler(DWORD dwCtrlType);
543int kill_signal_by_handle(HANDLE process, int sig); 544int kill_signal_by_handle(HANDLE process, int sig);
544int FAST_FUNC is_valid_signal(int number); 545int FAST_FUNC is_valid_signal(int number);
545 546
diff --git a/win32/process.c b/win32/process.c
index ebc006d4e..6abc329da 100644
--- a/win32/process.c
+++ b/win32/process.c
@@ -369,11 +369,46 @@ mingw_spawn_proc(const char **argv)
369 return mingw_spawnvp(P_NOWAIT, argv[0], (char *const *)argv); 369 return mingw_spawnvp(P_NOWAIT, argv[0], (char *const *)argv);
370} 370}
371 371
372BOOL WINAPI kill_child_ctrl_handler(DWORD dwCtrlType)
373{
374 static pid_t child_pid = 0;
375 DWORD dummy, *procs, count, rcount, i;
376
377 if (child_pid == 0) {
378 // First call sets child pid
379 child_pid = dwCtrlType;
380 return FALSE;
381 }
382
383 if (dwCtrlType == CTRL_C_EVENT || dwCtrlType == CTRL_BREAK_EVENT) {
384 count = GetConsoleProcessList(&dummy, 1) + 16;
385 procs = malloc(sizeof(DWORD) * count);
386 rcount = GetConsoleProcessList(procs, count);
387 if (rcount != 0 && rcount <= count) {
388 for (i = 0; i < rcount; i++) {
389 if (procs[i] == child_pid) {
390 // Child is attached to our console
391 break;
392 }
393 }
394 if (i == rcount) {
395 // Kill non-console child; console children can
396 // handle Ctrl-C as they see fit.
397 kill(-child_pid, SIGINT);
398 }
399 }
400 free(procs);
401 return TRUE;
402 }
403 return FALSE;
404}
405
372static NORETURN void wait_for_child(HANDLE child) 406static NORETURN void wait_for_child(HANDLE child)
373{ 407{
374 DWORD code; 408 DWORD code;
375 409
376 SetConsoleCtrlHandler(NULL, TRUE); 410 kill_child_ctrl_handler(GetProcessId(child));
411 SetConsoleCtrlHandler(kill_child_ctrl_handler, TRUE);
377 WaitForSingleObject(child, INFINITE); 412 WaitForSingleObject(child, INFINITE);
378 GetExitCodeProcess(child, &code); 413 GetExitCodeProcess(child, &code);
379 exit((int)code); 414 exit((int)code);