aboutsummaryrefslogtreecommitdiff
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
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.
-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 */