Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 11 Feb 1998 04:42:20 +1100
From:      Bruce Evans <bde@zeta.org.au>
To:        bde@zeta.org.au, cracauer@cons.org
Cc:        freebsd-current@FreeBSD.ORG
Subject:   Re: cvs commit: src/bin/sh jobs.c
Message-ID:  <199802101742.EAA16027@godzilla.zeta.org.au>

next in thread | raw e-mail | index | archive | help
>The patch below makes sh pass all my tests. In addition to the last
>...
>***************
>*** 575,580 ****
>--- 578,593 ----
>  	    mode));
>  	INTOFF;
>+ 	if (mode == FORK_FG) {

Add ` || mode == FORK_NOJOB'

>***************
>*** 587,590 ****
>--- 600,607 ----
>  
>  		TRACE(("Child shell %d\n", getpid()));
>+ 		if (oldsigquit != SIG_IGN)
>+ 			signal(SIGQUIT,SIG_DFL);
>+ 		if (oldsigint != SIG_IGN)
>+ 			signal(SIGINT,SIG_DFL);

Add `if (oldsigs_valid) ...

I checked an old draft of POSIX.2.  The main points about signal handling
seem to be:

1. For async commands, SIGINT and SIGQUIT from the keyboard shall be
   prevented from interrupting the command.  Otherwise, signal handling
   shall be inherited from the shell's parent.

Notes.  This seems to require SIGINT and SIGQUIT not from the keyboard
to not be handled specially.  (How can the shell tell whether stdin is
connected to _the_ keyboard? ;-).  This doesn't specify handling of
signals by the shell itself.

2. If the shell is waiting for a forground command, and a signal with a
   trap handler is received, then "the trap shall not be executed until
   after the foreground command has been completed".

Notes.  Presumably, trapped signals are supposed to be received and not
just ignored while waiting for a command.  Your change breaks this in
most cases, since the shell ignores SIGINT and SIGQUIT while waiting.
The SIGINT case still works, accidentally, when the foreground command
is killed by a SIGINT.  Then the shell forwards the signal to itself
after it restores its signal catcher.  This can probably be fixed
by replacing the signal(..., SIG_IGN)'s by a sigprocmask(SIG_BLOCK,
...), etc.  Signals will be delayed until they are unblocked after the
command completes, but this is precisely what is wanted.

Traps are also handled strangely in interactive shells when the shell is
not waiting for a command.  They are not executed until the next command
completes.

3. If the shell is waiting (via the wait command) for a background
   command, then the wait command shall exit immediately on receipt of
   a signal, and then the trap shall be executed.  

Notes.  This is very broken in all versions of sh.  Both the command
and the wait builtin seem to ignore all keyboard signals.  It works
in bash.

4. For subshells, traps caught by the shell shall be set to the default
   values and traps ignored by the shell shall be ignored by the command.

Notes.  "the default values" doesn't seem to be specified.  It presumably
means that the corresponding signals are set to SIG_DFL.  The initial
state of trap handlers doesn't seem to be specified anywhere.  I think
this means that sh's handling of signals is already correct, but bash's.
handling of subshells is incorrect.  If you want to set the signal
handling portably, then you must use `trap'.  This makes sense, since
changing from from SIG_DFL to SIG_IGN is easy, while changing from SIG_IGN
to SIG_DFL is impossible (the best you can do is attempt to kill the shell
from the trap handler) and wrong if anything except the shell set SIG_IGN.
Examples (where catchint exits normally when killed by SIGINT):

(a) while :; do catchint; done		# interactive

The shell may be killed by a SIGINT.  To ensure the usual handling, you
must use "trap '' SIGINT".  It is not an error for the shell to ignore
SIGINT. (?)

(b) #!/bin/sh
    while :; do catchint; done

Same as (a).  "the default values" in for the trap handlers are not
specified to be different for interactive shells.  (?)

(c) #!/bin/sh
    (while :; do catchint; done)

Now there is a subshell.  It must be killed by SIGINT. (?)

(PR1206) /bin/sh -c "trap '' SIGINT; emacs"

The command must be written something like this to ensure ignoring of
SIGINT.

Bruce

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe current" in the body of the message



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199802101742.EAA16027>