Skip site navigation (1)Skip section navigation (2)
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>