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
commit89aa9d783c535670c6aed1d32c8740b7474cca00 (patch)
tree52a494ad5f8a89fbdb5ad2a6155a62d7d3a6a024
parentc2c0cfbeb6f07fa3257a60760d5c8a5382cee6e9 (diff)
downloadbusybox-w32-89aa9d783c535670c6aed1d32c8740b7474cca00.tar.gz
busybox-w32-89aa9d783c535670c6aed1d32c8740b7474cca00.tar.bz2
busybox-w32-89aa9d783c535670c6aed1d32c8740b7474cca00.zip
win32: changes to signal handling
Use an exit code of the form (signal << 24) when a process exits due to a signal. This replaces the previous use of (signal + 128). This makes it easier to distinguish exit codes from signals. Allow kill(2) to handle all defined signals, not just EXIT, TERM and KILL. The kill and timeout applets now accept any defined signals. Convert certain Windows status codes Unix-style signal codes. In ash: - Exit as if with SIGINT in raise_interrupt() rather than call raise(SIGINT). The latter returns an exit code of 3. - Detect if a child process exits as if with SIGINT. If not and if the parent is an interactive top-level shell, reset pending_int. This prevents the parent from seeing an INT if the child hasn't reported it exited due to INT. (Probably due to it being an interactive shell.) Costs 132-136 bytes.
-rw-r--r--coreutils/timeout.c4
-rw-r--r--findutils/xargs.c2
-rw-r--r--include/mingw.h3
-rw-r--r--shell/ash.c31
-rw-r--r--win32/process.c21
5 files changed, 43 insertions, 18 deletions
diff --git a/coreutils/timeout.c b/coreutils/timeout.c
index 3565c005d..8f306529f 100644
--- a/coreutils/timeout.c
+++ b/coreutils/timeout.c
@@ -54,7 +54,7 @@ static HANDLE child = INVALID_HANDLE_VALUE;
54static void kill_child(void) 54static void kill_child(void)
55{ 55{
56 if (child != INVALID_HANDLE_VALUE) { 56 if (child != INVALID_HANDLE_VALUE) {
57 kill_SIGTERM_by_handle(child); 57 kill_signal_by_handle(child, SIGTERM);
58 } 58 }
59} 59}
60 60
@@ -130,7 +130,7 @@ int timeout_main(int argc UNUSED_PARAM, char **argv)
130#if !ENABLE_PLATFORM_MINGW32 130#if !ENABLE_PLATFORM_MINGW32
131 if (signo < 0) 131 if (signo < 0)
132#else 132#else
133 if (signo != SIGTERM && signo != SIGKILL && signo != 0) 133 if (!is_valid_signal(signo))
134#endif 134#endif
135 bb_error_msg_and_die("unknown signal '%s'", opt_s); 135 bb_error_msg_and_die("unknown signal '%s'", opt_s);
136 136
diff --git a/findutils/xargs.c b/findutils/xargs.c
index bc47a869f..1e7d8de02 100644
--- a/findutils/xargs.c
+++ b/findutils/xargs.c
@@ -216,7 +216,7 @@ static BOOL WINAPI ctrl_handler(DWORD dwCtrlType)
216 } 216 }
217 } 217 }
218# endif 218# endif
219 exit(128 + SIGINT); 219 exit(SIGINT << 24);
220 return TRUE; 220 return TRUE;
221 } 221 }
222 return FALSE; 222 return FALSE;
diff --git a/include/mingw.h b/include/mingw.h
index 6204ded6d..f94804d91 100644
--- a/include/mingw.h
+++ b/include/mingw.h
@@ -540,7 +540,8 @@ 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
543int kill_SIGTERM_by_handle(HANDLE process); 543int kill_signal_by_handle(HANDLE process, int sig);
544int FAST_FUNC is_valid_signal(int number);
544 545
545#define find_mount_point(n, s) find_mount_point(n) 546#define find_mount_point(n, s) find_mount_point(n)
546 547
diff --git a/shell/ash.c b/shell/ash.c
index 93c402a8b..87df555dd 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -884,9 +884,13 @@ raise_interrupt(void)
884 /* pending_sig = 0; - now done in signal_handler() */ 884 /* pending_sig = 0; - now done in signal_handler() */
885 885
886 if (!(rootshell && iflag)) { 886 if (!(rootshell && iflag)) {
887#if !ENABLE_PLATFORM_MINGW32
887 /* Kill ourself with SIGINT */ 888 /* Kill ourself with SIGINT */
888 signal(SIGINT, SIG_DFL); 889 signal(SIGINT, SIG_DFL);
889 raise(SIGINT); 890 raise(SIGINT);
891#else
892 exit(SIGINT << 24);
893#endif
890 } 894 }
891#if ENABLE_PLATFORM_MINGW32 895#if ENABLE_PLATFORM_MINGW32
892 if (iflag) 896 if (iflag)
@@ -4122,8 +4126,10 @@ struct job {
4122#define JOBDONE 2 /* all procs are completed */ 4126#define JOBDONE 2 /* all procs are completed */
4123 unsigned 4127 unsigned
4124 state: 8, 4128 state: 8,
4125#if JOBS 4129#if JOBS || ENABLE_PLATFORM_MINGW32
4126 sigint: 1, /* job was killed by SIGINT */ 4130 sigint: 1, /* job was killed by SIGINT */
4131#endif
4132#if JOBS
4127 jobctl: 1, /* job running under job control */ 4133 jobctl: 1, /* job running under job control */
4128#endif 4134#endif
4129 waited: 1, /* true if this entry has been waited for */ 4135 waited: 1, /* true if this entry has been waited for */
@@ -4840,7 +4846,7 @@ waitpid_child(int *status, int wait_flags)
4840 HANDLE *proclist; 4846 HANDLE *proclist;
4841 pid_t pid = -1; 4847 pid_t pid = -1;
4842 DWORD win_status, idx; 4848 DWORD win_status, idx;
4843 int i; 4849 int i, sig;
4844 4850
4845 for (jb = curjob; jb; jb = jb->prev_job) { 4851 for (jb = curjob; jb; jb = jb->prev_job) {
4846 if (jb->state != JOBDONE) 4852 if (jb->state != JOBDONE)
@@ -4872,9 +4878,18 @@ waitpid_child(int *status, int wait_flags)
4872 wait_flags&WNOHANG ? 1 : INFINITE); 4878 wait_flags&WNOHANG ? 1 : INFINITE);
4873 if (idx < pid_nr) { 4879 if (idx < pid_nr) {
4874 GetExitCodeProcess(proclist[idx], &win_status); 4880 GetExitCodeProcess(proclist[idx], &win_status);
4875 *status = (int)win_status << 8; 4881 if (win_status == 0xc0000005)
4876 if (win_status == 128 + SIGTERM || win_status == 128 + SIGKILL) 4882 win_status = SIGSEGV << 24;
4877 *status += win_status - 128; 4883 else if (win_status == 0xc000013a)
4884 win_status = SIGINT << 24;
4885
4886 // When a process is terminated as if by a signal the exit
4887 // code is zero apart from the signal in its topmost byte.
4888 sig = win_status >> 24;
4889 if (sig != 0 && win_status == sig << 24 && is_valid_signal(sig))
4890 *status = sig;
4891 else
4892 *status = (int)win_status << 8;
4878 pid = pidlist[idx]; 4893 pid = pidlist[idx];
4879 } 4894 }
4880 done: 4895 done:
@@ -5241,7 +5256,7 @@ getstatus(struct job *job)
5241 { 5256 {
5242 /* XXX: limits number of signals */ 5257 /* XXX: limits number of signals */
5243 retval = WTERMSIG(status); 5258 retval = WTERMSIG(status);
5244#if JOBS 5259#if JOBS || ENABLE_PLATFORM_MINGW32
5245 if (retval == SIGINT) 5260 if (retval == SIGINT)
5246 job->sigint = 1; 5261 job->sigint = 1;
5247#endif 5262#endif
@@ -6051,6 +6066,10 @@ waitforjob(struct job *jp)
6051 return exitstatus; 6066 return exitstatus;
6052 6067
6053 st = getstatus(jp); 6068 st = getstatus(jp);
6069#if ENABLE_PLATFORM_MINGW32
6070 if (!jp->sigint && iflag && rootshell)
6071 pending_int = 0;
6072#endif
6054#if JOBS 6073#if JOBS
6055 if (jp->jobctl) { 6074 if (jp->jobctl) {
6056 xtcsetpgrp(ttyfd, rootpid); 6075 xtcsetpgrp(ttyfd, rootpid);
diff --git a/win32/process.c b/win32/process.c
index 228b0b30e..ebc006d4e 100644
--- a/win32/process.c
+++ b/win32/process.c
@@ -705,14 +705,14 @@ static inline int process_architecture_matches_current(HANDLE process)
705 * http://www.drdobbs.com/a-safer-alternative-to-terminateprocess/184416547 705 * http://www.drdobbs.com/a-safer-alternative-to-terminateprocess/184416547
706 * 706 *
707 */ 707 */
708int kill_SIGTERM_by_handle(HANDLE process) 708int kill_signal_by_handle(HANDLE process, int sig)
709{ 709{
710 DWORD code; 710 DWORD code;
711 int ret = 0; 711 int ret = 0;
712 712
713 if (GetExitCodeProcess(process, &code) && code == STILL_ACTIVE) { 713 if (GetExitCodeProcess(process, &code) && code == STILL_ACTIVE) {
714 DECLARE_PROC_ADDR(DWORD, ExitProcess, LPVOID); 714 DECLARE_PROC_ADDR(DWORD, ExitProcess, LPVOID);
715 PVOID arg = (PVOID)(intptr_t)(128 + SIGTERM); 715 PVOID arg = (PVOID)(intptr_t)(sig << 24);
716 DWORD thread_id; 716 DWORD thread_id;
717 HANDLE thread; 717 HANDLE thread;
718 718
@@ -734,7 +734,7 @@ int kill_SIGTERM_by_handle(HANDLE process)
734 return ret; 734 return ret;
735} 735}
736 736
737static int kill_SIGTERM(pid_t pid, int sig UNUSED_PARAM) 737static int kill_signal(pid_t pid, int sig)
738{ 738{
739 HANDLE process; 739 HANDLE process;
740 740
@@ -745,7 +745,7 @@ static int kill_SIGTERM(pid_t pid, int sig UNUSED_PARAM)
745 return -1; 745 return -1;
746 } 746 }
747 747
748 return kill_SIGTERM_by_handle(process); 748 return kill_signal_by_handle(process, sig);
749} 749}
750 750
751/* 751/*
@@ -765,18 +765,23 @@ static int kill_SIGKILL(pid_t pid, int sig)
765 } 765 }
766 766
767 if (sig == SIGKILL) 767 if (sig == SIGKILL)
768 ret = !TerminateProcess(process, 128 + SIGKILL); 768 ret = !TerminateProcess(process, SIGKILL << 24);
769 CloseHandle(process); 769 CloseHandle(process);
770 770
771 return ret; 771 return ret;
772} 772}
773 773
774int FAST_FUNC is_valid_signal(int number)
775{
776 return isalpha(*get_signame(number));
777}
778
774int kill(pid_t pid, int sig) 779int kill(pid_t pid, int sig)
775{ 780{
776 if (sig == SIGTERM) 781 if (sig == SIGKILL || sig == 0)
777 return kill_pids(pid, sig, kill_SIGTERM);
778 else if (sig == SIGKILL || sig == 0)
779 return kill_pids(pid, sig, kill_SIGKILL); 782 return kill_pids(pid, sig, kill_SIGKILL);
783 else if (is_valid_signal(sig))
784 return kill_pids(pid, sig, kill_signal);
780 785
781 errno = EINVAL; 786 errno = EINVAL;
782 return -1; 787 return -1;