From owner-freebsd-bugs Sun Nov 10 06:01:27 1996 Return-Path: owner-bugs Received: (from root@localhost) by freefall.freebsd.org (8.7.5/8.7.3) id GAA10112 for bugs-outgoing; Sun, 10 Nov 1996 06:01:27 -0800 (PST) Received: from godzilla.zeta.org.au (godzilla.zeta.org.au [203.2.228.19]) by freefall.freebsd.org (8.7.5/8.7.3) with ESMTP id GAA10101 for ; Sun, 10 Nov 1996 06:01:14 -0800 (PST) Received: (from bde@localhost) by godzilla.zeta.org.au (8.7.6/8.6.9) id AAA09298; Mon, 11 Nov 1996 00:59:08 +1100 Date: Mon, 11 Nov 1996 00:59:08 +1100 From: Bruce Evans Message-Id: <199611101359.AAA09298@godzilla.zeta.org.au> To: freebsd-bugs@freefall.freebsd.org, peter@spinner.DIALix.COM Subject: Re: bin/1990 Sender: owner-bugs@FreeBSD.ORG X-Loop: FreeBSD.org Precedence: bulk > A possible fix for the make/sh bug with SIGINT: > > - if (minusc) { > + if (minusc && !eflag) { I think this breaks the -e case in a different way. I think the shell wait for the command to exit (even if not -c), and then: a) if the the command was killed by a signal, exit. b) if the exit status was nonzero, exit if -e, else continue. c) if the exit status was 0, always continue. This is complicated by job control and traps. > This makes 'sh -ec' consider SIGINT as an 'error' worth aborting, and > stops the long 'make fetch' command on ^C as it should. > Incidently, I could find no other shells that ignored SIGINT while doing > a 'sh -c' command.. Is this code really legitimate?? It looks like a > gratuitous incompatability with "other" systems... bash ignores the signal until the command completes, even without -c. So does my version of sh. Bash seems to have similar bugs in the -e case. Note that `fetch' catches SIGINT and exits with status 1, so the shell has to catch signals if it wants to specially handle the case where a signal ocurred. Here is a simpler example: q.c --- #include void die(int s) { exit(1); } int main(void) { signal(SIGINT, die); while (1) ; } --- shellprog: --- #!/bin/sh while :; do ./q; echo $?; done --- This can be killed by exploiting the races in the loop (signals are only masked while ./q is excecuting). There's something broken apart from the signal handling changes for $? to be 1 and the loop to continue in the -e case! There seem to be some races in the code too - signals aren't masked until after forking. However, I think the sigactions (in eval.c) are the wrong way to do the masking. I think INTON/INTOFF are supposed to work by trapping signals and deciding how to handle them later. Other examples: cat shellprog | bash -e # works correctly (aborts before echoing 1) cat shellprog | sh -e # same cat shellprog | bash # wants to loop for ever, even for SIGQUIT cat shellprog | sh # same (with my version of sh) Bruce