From owner-freebsd-current Tue Feb 10 09:45:27 1998 Return-Path: Received: (from majordom@localhost) by hub.freebsd.org (8.8.8/8.8.8) id JAA08943 for current-outgoing; Tue, 10 Feb 1998 09:45:27 -0800 (PST) (envelope-from owner-freebsd-current@FreeBSD.ORG) Received: from godzilla.zeta.org.au (godzilla.zeta.org.au [203.2.228.19]) by hub.freebsd.org (8.8.8/8.8.8) with ESMTP id JAA08934 for ; Tue, 10 Feb 1998 09:45:20 -0800 (PST) (envelope-from bde@godzilla.zeta.org.au) Received: (from bde@localhost) by godzilla.zeta.org.au (8.8.7/8.8.7) id EAA16027; Wed, 11 Feb 1998 04:42:20 +1100 Date: Wed, 11 Feb 1998 04:42:20 +1100 From: Bruce Evans Message-Id: <199802101742.EAA16027@godzilla.zeta.org.au> To: bde@zeta.org.au, cracauer@cons.org Subject: Re: cvs commit: src/bin/sh jobs.c Cc: freebsd-current@FreeBSD.ORG Sender: owner-freebsd-current@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.ORG >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