Date: Thu, 5 Feb 1998 20:28:24 +0100 From: Martin Cracauer <cracauer@cons.org> To: cvs-commiters@FreeBSD.ORG Subject: Please review fix for /bin/sh SIGQUIT/SIGINT problem Message-ID: <19980205202824.51394@cons.org>
next in thread | raw e-mail | index | archive | help
I'd like to commit the following patch to /bin/sh. If you think it isn't the right thing, please let me know ASAP. This fixes the problem that our /bin/sh (unlike csh, bash etc.) exits on SIGQUIT and SIGINT when a child is being run. The shell is exited, leaving the child with non-functional /dev/tty. See PR bin/1206. See also a problematic solution in version 1.7 or src/bin/sh/eval.c. The solution here is taken from csh: before a fork in sh, set SIGINT and SIGQUIT to SIG_IGN. In the child immedeatly set both to SIG_DFL. The parent waits for the child, then resets them to default. The cases I tested my patch against are: 1) SIGINT and SIGQUIT are ignored in an interactive shell. 2) SIGINT and SIGQUIT work as expected when a child caughts them: The child gets them to their handlers, the parent shell doesn't terminate. 3) The shell exits on SIGINT and SIGQUIT before and after running subprocesses. The problem here is that if you don't restore the signals, the shell script after any fork() will not be interruptable. test case: #!/bin/sh emacs -nw something while `true` ; do foo=1 ; done My proposed fix makes the emacs work right (uses SIGINT/SIGQUIT as expected, shell doesn't exit) and after emacs exits, you can break the shell loop by SIGINT or SIGQUIT. 4) My solutions works both for the "sh -c ./sigcatcher" and #!/bin/sh ./sigcatcher cases. I think this is complete, if anyone sees more worms creeping out of this can, please let me know. If the fix is complete, it is a 2.2-candidate. Happy hacking Martin diff -r -c sh.original/jobs.c sh/jobs.c *** sh.original/jobs.c Mon Mar 10 10:53:43 1997 --- sh/jobs.c Thu Feb 5 19:51:15 1998 *************** *** 553,558 **** --- 553,560 ---- TRACE(("forkshell(%%%d, 0x%lx, %d) called\n", jp - jobtab, (long)n, mode)); INTOFF; + signal(SIGQUIT,SIG_IGN); + signal(SIGINT,SIG_IGN); pid = fork(); if (pid == -1) { TRACE(("Fork failed, errno=%d\n", errno)); *************** *** 565,570 **** --- 567,574 ---- int i; TRACE(("Child shell %d\n", getpid())); + signal(SIGQUIT,SIG_DFL); + signal(SIGINT,SIG_DFL); wasroot = rootshell; rootshell = 0; for (i = njobs, p = jobtab ; --i >= 0 ; p++) *************** *** 674,679 **** --- 678,686 ---- while (jp->state == 0) { dowait(1, jp); } + signal(SIGQUIT,SIG_DFL); + signal(SIGINT,SIG_DFL); + #if JOBS if (jp->jobctl) { if (ioctl(2, TIOCSPGRP, (char *)&mypgrp) < 0) -- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Martin Cracauer <cracauer@cons.org> http://www.cons.org/cracauer cracauer@wavehh.hanse.de (batched, preferred for large mails) Tel.: (daytime) +4940 41478712 Fax.: (daytime) +4940 41478715 Tel.: (private) +4940 5221829 Fax.: (private) +4940 5228536 Paper: (private) Waldstrasse 200, 22846 Norderstedt, Germany
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?19980205202824.51394>