diff options
author | Ron Yorston <rmy@pobox.com> | 2023-05-23 10:57:56 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2023-05-23 10:57:56 +0100 |
commit | 20b6a57af64506a4152b145b031aad2946a37ca8 (patch) | |
tree | c92e38c5e72e1b7ac36845a15967d6f4fe60c8f7 | |
parent | 89aa9d783c535670c6aed1d32c8740b7474cca00 (diff) | |
download | busybox-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.h | 1 | ||||
-rw-r--r-- | win32/process.c | 37 |
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 | ||
543 | BOOL WINAPI kill_child_ctrl_handler(DWORD dwCtrlType); | ||
543 | int kill_signal_by_handle(HANDLE process, int sig); | 544 | int kill_signal_by_handle(HANDLE process, int sig); |
544 | int FAST_FUNC is_valid_signal(int number); | 545 | int 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 | ||
372 | BOOL 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 | |||
372 | static NORETURN void wait_for_child(HANDLE child) | 406 | static 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); |