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 | 89aa9d783c535670c6aed1d32c8740b7474cca00 (patch) | |
tree | 52a494ad5f8a89fbdb5ad2a6155a62d7d3a6a024 /shell | |
parent | c2c0cfbeb6f07fa3257a60760d5c8a5382cee6e9 (diff) | |
download | busybox-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.
Diffstat (limited to 'shell')
-rw-r--r-- | shell/ash.c | 31 |
1 files changed, 25 insertions, 6 deletions
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); |