Bug 84667
Summary: | shell script still runs next command after ^C | ||
---|---|---|---|
Product: | [Retired] Red Hat Linux | Reporter: | Alexandre Oliva <aoliva> |
Component: | bash | Assignee: | Arjan van de Ven <arjanv> |
Status: | CLOSED NOTABUG | QA Contact: | Brian Brock <bbrock> |
Severity: | medium | Docs Contact: | |
Priority: | medium | ||
Version: | 9 | CC: | mitr |
Target Milestone: | --- | ||
Target Release: | --- | ||
Hardware: | i386 | ||
OS: | Linux | ||
Whiteboard: | |||
Fixed In Version: | Doc Type: | Bug Fix | |
Doc Text: | Story Points: | --- | |
Clone Of: | Environment: | ||
Last Closed: | 2003-12-10 16:08:36 UTC | Type: | --- |
Regression: | --- | Mount Type: | --- |
Documentation: | --- | CRM: | |
Verified Versions: | Category: | --- | |
oVirt Team: | --- | RHEL 7.3 requirements from Atomic Host: | |
Cloudforms Team: | --- | Target Upstream Version: | |
Embargoed: |
Description
Alexandre Oliva
2003-02-20 05:19:23 UTC
Looking in /proc/pid/status I observe that the sleep processes are all ignoring SIGINT. Both they and the sh processes are also ignoring SIGQUIT, which is odd. In just "sh -c 'sleep 999'", the sh process ignores SIGQUIT but the sleep process does not ignore any signals. I guess ignoring SIGQUIT itself is the shell's business, though it seems odd. An strace shows that the shell ignores SIGINT after fork and before exec'ing sleep. It also suspiciously redirects < /dev/null, which was never requested. 22747 access("/bin/sleep", X_OK) = 0 22747 rt_sigaction(SIGINT, {SIG_DFL}, {SIG_DFL}, 8) = 0 22747 rt_sigaction(SIGQUIT, {SIG_DFL}, {SIG_IGN}, 8) = 0 22747 rt_sigaction(SIGCHLD, {SIG_DFL}, {0x8076d30, [], SA_RESTORER, 0x420277e8}, 8) = 0 22747 open("/dev/null", O_RDONLY|O_LARGEFILE) = 3 22747 dup2(3, 0) = 0 22747 close(3) = 0 22747 rt_sigaction(SIGINT, {SIG_IGN}, {SIG_DFL}, 8) = 0 22747 rt_sigaction(SIGQUIT, {SIG_IGN}, {SIG_DFL}, 8) = 0 22747 execve("/bin/sleep", ["sleep", "300"], [/* 28 vars */]) = 0 In fact, all of this looks like intentionally UTTERLY WRONG code in bash. See execute_cmd.c, and its misguided functions async_redirect_stdin and setup_async_signals. bash has decided that when you say "foo &", you really meant: (trap '' SIGINT SIGQUIT; exec foo < /dev/null) & Go figure. Somebody must be on crack. These patently stupid behaviors seem to have been specified by the 2001 version of POSIX. They have clearly gone nuts. The redirection from /dev/null is just screwy, and utterly wrong and antiuseful in an interactive shell, but now POSIX seems to specify it in a way that does not AFAICT distinguish between scripts and interactive shells. Likewise ignoring SIGQUIT and SIGINT in background jobs makes sense in interactive shells not supporting job control, but is right loopy for scripts. I have not tried to read the entire chapter for all possible context, but it too seems to be specified without regard for the distinction between sane behavior for interactive shells and for scripts. Gee, how did this end up filed under kernel? I was sure I had changed it to bash after some investigation before posting. Obviously I was wrong... Oh, well... Sorry. It didn't get reassigned to me, so this is the first time I've seen it (by chance). So is this behaviour POSIX-mandated? Chet Ramey believes that bash is doing the right thing here: "Bash notes that it receives the SIGINT but waits until the background jobs have completed before acting on it. Since the background jobs ignore keyboard-generated SIGINTs, they don't exit until they're done. `wait' would return immediately if there were a trap on SIGINT, though. POSIX specifies that, too." |