aboutsummaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2020-06-20 12:13:57 +0100
committerRon Yorston <rmy@pobox.com>2020-06-20 12:13:57 +0100
commit53aca1b56db730b0103f5ec2e692327237a775e2 (patch)
tree3f84a84b3e2728f424db141e19dfb5118e964025 /shell
parentda7c8cdf631fc0754d30d5b997ee71a085699469 (diff)
downloadbusybox-w32-53aca1b56db730b0103f5ec2e692327237a775e2.tar.gz
busybox-w32-53aca1b56db730b0103f5ec2e692327237a775e2.tar.bz2
busybox-w32-53aca1b56db730b0103f5ec2e692327237a775e2.zip
ash: changes to ctrl-c handling
Make ctrl-c handling more like Unix. Remove the hSIGINT event and the code in waitpid_child() to catch it. Add a call to raise_interrupt() in ctrl_handler(). Prior to these changes interrupts in a child shell weren't properly handled. In release FRP-3466-g53c09d0e1 interrupting a sleep in a child shell results in both shells competing for input: ~ $ sh ~ $ sleep 10 ^C^C ~ $ ~ $ pwd sh: w: not found ~ $ sh: pd: not found ~ $ With recent changes: ~ $ sh ~ $ sleep 10 ^C ~ $ echo $? 130 ~ $ exit ^C ~ $ echo $? 130 ~ $ The error return from the parent shell is due to the lack of job control. Upstream BusyBox ash and dash both do the same when job control is disabled.
Diffstat (limited to 'shell')
-rw-r--r--shell/ash.c70
1 files changed, 13 insertions, 57 deletions
diff --git a/shell/ash.c b/shell/ash.c
index f11449530..decd6c0f7 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -771,6 +771,10 @@ raise_interrupt(void)
771 signal(SIGINT, SIG_DFL); 771 signal(SIGINT, SIG_DFL);
772 raise(SIGINT); 772 raise(SIGINT);
773 } 773 }
774#if ENABLE_PLATFORM_MINGW32
775 if (iflag)
776 write(STDOUT_FILENO, "^C", 2);
777#endif
774 /* bash: ^C even on empty command line sets $? */ 778 /* bash: ^C even on empty command line sets $? */
775 exitstatus = SIGINT + 128; 779 exitstatus = SIGINT + 128;
776 raise_exception(EXINT); 780 raise_exception(EXINT);
@@ -4656,14 +4660,12 @@ sprint_status48(char *os, int status, int sigonly)
4656} 4660}
4657 4661
4658#if ENABLE_PLATFORM_MINGW32 4662#if ENABLE_PLATFORM_MINGW32
4659
4660HANDLE hSIGINT; /* Ctrl-C is pressed */
4661
4662static BOOL WINAPI ctrl_handler(DWORD dwCtrlType) 4663static BOOL WINAPI ctrl_handler(DWORD dwCtrlType)
4663{ 4664{
4664 if (dwCtrlType == CTRL_C_EVENT || dwCtrlType == CTRL_BREAK_EVENT) { 4665 if (dwCtrlType == CTRL_C_EVENT || dwCtrlType == CTRL_BREAK_EVENT) {
4666 if (!suppress_int)
4667 raise_interrupt(); /* does not return */
4665 pending_int = 1; 4668 pending_int = 1;
4666 SetEvent(hSIGINT);
4667 return TRUE; 4669 return TRUE;
4668 } 4670 }
4669 return FALSE; 4671 return FALSE;
@@ -4683,21 +4685,19 @@ waitpid_child(int *status, int wait_flags)
4683 HANDLE *proclist; 4685 HANDLE *proclist;
4684 pid_t pid = -1; 4686 pid_t pid = -1;
4685 DWORD win_status, idx; 4687 DWORD win_status, idx;
4686 int i, delay; 4688 int i;
4687 4689
4688 for (jb = curjob; jb; jb = jb->prev_job) { 4690 for (jb = curjob; jb; jb = jb->prev_job) {
4689 if (jb->state != JOBDONE) 4691 if (jb->state != JOBDONE)
4690 pid_nr += jb->nprocs; 4692 pid_nr += jb->nprocs;
4691 } 4693 }
4692 if ( pid_nr++ == 0 ) 4694 if (pid_nr == 0)
4693 return -1; 4695 return -1;
4694 4696
4695 pidlist = ckmalloc(sizeof(*pidlist)*pid_nr); 4697 pidlist = ckmalloc(sizeof(*pidlist)*pid_nr);
4696 proclist = ckmalloc(sizeof(*proclist)*pid_nr); 4698 proclist = ckmalloc(sizeof(*proclist)*pid_nr);
4697 4699
4698 pidlist[0] = -1; 4700 pid_nr = 0;
4699 proclist[0] = hSIGINT;
4700 pid_nr = 1;
4701 for (jb = curjob; jb; jb = jb->prev_job) { 4701 for (jb = curjob; jb; jb = jb->prev_job) {
4702 if (jb->state == JOBDONE) 4702 if (jb->state == JOBDONE)
4703 continue; 4703 continue;
@@ -4710,56 +4710,15 @@ waitpid_child(int *status, int wait_flags)
4710 } 4710 }
4711 } 4711 }
4712 4712
4713 if (pid_nr == 1) 4713 if (pid_nr == 0)
4714 goto done; 4714 goto done;
4715 4715
4716 idx = WaitForMultipleObjects(pid_nr, proclist, FALSE, 4716 idx = WaitForMultipleObjects(pid_nr, proclist, FALSE,
4717 wait_flags&WNOHANG ? 1 : INFINITE); 4717 wait_flags&WNOHANG ? 1 : INFINITE);
4718 if (idx < pid_nr) { 4718 if (idx < pid_nr) {
4719 if (idx == 0) { /* hSIGINT */ 4719 GetExitCodeProcess(proclist[idx], &win_status);
4720 ResetEvent(hSIGINT); 4720 *status = (int)win_status << 8;
4721 4721 pid = pidlist[idx];
4722 ps = curjob->ps;
4723 for (i = 0; i < curjob->nprocs; ++i) {
4724 if (ps[i].ps_proc) {
4725 kill_SIGTERM_by_handle(ps[i].ps_proc, 128+SIGINT);
4726 pid = ps[i].ps_pid; /* remember last valid pid */
4727 }
4728 }
4729
4730 Sleep(200);
4731 delay = FALSE;
4732 for (i = 0; i < curjob->nprocs; ++i) {
4733 DWORD code;
4734 if (ps[i].ps_proc &&
4735 GetExitCodeProcess(ps[i].ps_proc, &code) &&
4736 code == STILL_ACTIVE) {
4737 TerminateProcess(ps[i].ps_proc, 128+SIGINT);
4738 delay = TRUE;
4739 }
4740 }
4741
4742 if (delay)
4743 Sleep(200);
4744 for (i = 0; i < curjob->nprocs; ++i) {
4745 /* mark all pids dead except the one we'll return */
4746 if (ps[i].ps_pid != pid) {
4747 ps[i].ps_status = 128 + SIGINT;
4748 ps[i].ps_pid = -1;
4749 CloseHandle(ps[i].ps_proc);
4750 ps[i].ps_proc = NULL;
4751 }
4752 }
4753
4754 *status = 128 + SIGINT; /* terminated by a signal */
4755 if (iflag)
4756 write(STDOUT_FILENO, "^C", 2);
4757 }
4758 else { /* valid pid index */
4759 GetExitCodeProcess(proclist[idx], &win_status);
4760 *status = (int)win_status << 8;
4761 pid = pidlist[idx];
4762 }
4763 } 4722 }
4764 done: 4723 done:
4765 free(pidlist); 4724 free(pidlist);
@@ -14821,7 +14780,6 @@ readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
14821 if ((uintptr_t)r == 2) { 14780 if ((uintptr_t)r == 2) {
14822 /* ^C pressed, propagate event */ 14781 /* ^C pressed, propagate event */
14823 if (iflag) { 14782 if (iflag) {
14824 write(STDOUT_FILENO, "^C", 2);
14825 raise_interrupt(); 14783 raise_interrupt();
14826 } 14784 }
14827 else { 14785 else {
@@ -15269,8 +15227,6 @@ int ash_main(int argc UNUSED_PARAM, char **argv)
15269 basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ); 15227 basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
15270 basepf.linno = 1; 15228 basepf.linno = 1;
15271 15229
15272 hSIGINT = CreateEvent(NULL, TRUE, FALSE, NULL);
15273
15274 if (argc == 3 && !strcmp(argv[1], "--fs")) { 15230 if (argc == 3 && !strcmp(argv[1], "--fs")) {
15275 forkshell_init(argv[2]); 15231 forkshell_init(argv[2]);
15276 /* only reached in case of error */ 15232 /* only reached in case of error */