When running an interactive command, dash doesn't ignore SIGINT
and SIGQUIT.
For instance, here's what I get with Emacs 24 (not a previous
version, since previously, Emacs had its own progress group,
so that the bug wasn't visible), by typing Ctrl-G Ctrl-X Ctrl-C
in Emacs:
$ bash -c "emacs -Q -nw; echo foo"; echo bar
foo
bar
$ dash -c "emacs -Q -nw; echo foo"; echo bar
$ echo $?
130
$
The main problem is that dash is generally used as /bin/sh, thus
by the system() command (or equivalent). So, typing Ctrl-G in an
Emacs running in a terminal has the effect to make the sh shell
fail, without any possible workaround. This affects applications
that run an editor such as Subversion (svn command) and Mutt.
For instance, with svn:
$ SVN_EDITOR=emacs svn ci
svn: E200012: Commit failed (details follow):
svn: E200012: system('emacs svn-commit.tmp') returned 2
svn: E200012: Your commit message was left in a temporary file:
svn: E200012: '/home/vinc17/wd/db/svn-commit.tmp'
zsh: interrupt SVN_EDITOR=emacs svnwrapper ci
According to Andreas Schwab[*], this is a bug in dash. And indeed,
the system(3) man page says:
system() executes a command specified in command by calling
/bin/sh -c command, and returns after the command has been
completed. During execution of the command, SIGCHLD will be
blocked, and SIGINT and SIGQUIT will be ignored.
[*] http://debbugs.gnu.org/cgi/bugreport.cgi?bug=11886#17
severity 683671 serious # not Debian-specific tags 683671 + upstream moreinfo quit Hi Vincent, Vincent Lefevre wrote: Can you explain that more precisely? At first glance it seems like an ordinary important bug. [...] Thanks for the pointer. http://unix.org/2008edition/ tells me: When a command is in an asynchronous list, it shall inherit from the shell a signal action of ignored (SIG_IGN) for the SIGQUIT and SIGINT signals, and may inherit a signal mask in which SIGQUIT and SIGINT are blocked. Otherwise, the signal actions and signal mask inherited by the command shall be the same as those inherited by the shell from its parent unless a signal action is modified by the trap special built-in (see trap ) In 'sh -c "emacs -nw"', the emacs command is not in an asynchronous list, so I would suspect that emacs is supposed to inherit the same signal actions as the shell inherited. How about this patch (which at least gets rid of a mysterious code artifact)? Curious, Jonathan diff --git a/src/trap.c b/src/trap.c index 17316c9..1fa835b 100644 --- a/src/trap.c +++ b/src/trap.c @@ -347,7 +347,7 @@ setinteractive(int on) { static int is_interactive; - if (++on == is_interactive) + if (on == is_interactive) return; is_interactive = on; setsignal(SIGINT);
Hi Jonathan, Emacs is often called by other programs, and possibly from a /bin/sh script, with postprocessing. Here's a simple example: #!/bin/sh trap 'true' INT sh -c 'emacs -nw tmpfile; mv tmpfile newfile' rm -f tmpfile cat newfile rm -f newfile If Ctrl-G is typed in Emacs, the data are lost. Even though a correction could be done on such a simple example, in real applications, this is less obvious. And how do we do the difference between (1) a real SIGINT from Ctrl-C, meaning that the user is no longer interested in the data and clean-up can be done, and (2) a SIGINT coming from a bug, meaning that temporary files should be left on the disk and the user should guess where his data are and what they mean? This paragraph is about signals inherited by the command. Here the question is what the shell should do with SIGINT/SIGQUIT signals it receives while it is executing a command which is not killed by the signal? Not that how the command is affected by the signal is important. See the difference between: #!/bin/sh trap 'true' INT bash -c 'date > tmpfile; sleep 5; mv tmpfile newfile' rm -f tmpfile cat newfile rm -f newfile with Ctrl-C during the "sleep 5", and: #!/bin/sh trap 'true' INT bash -c 'date > tmpfile; emacs -nw; mv tmpfile newfile' rm -f tmpfile cat newfile rm -f newfile with Ctrl-G in Emacs. You can also try: #!/bin/sh trap 'true' INT bash -c 'date > tmpfile; gdb; mv tmpfile newfile' rm -f tmpfile cat newfile rm -f newfile with Ctrl-C in gdb. If bash is replaced by dash, one always gets a failure, not just in the first case. Since there was a similar problem with zsh and GNU Emacs under Mac OS X (and I really lost data several times, until I identified the problem, but contrary to here, the problem was occurring with all Emacs versions[*]), I now remember this page: http://www.cons.org/cracauer/sigint.html It probably gives the answer of what should be done. [*] http://www.zsh.org/mla/workers/2009/msg00926.html
Vincent Lefevre wrote: Weird. Why does system(3) claim it sets SIGINT to SIG_IGN, then? Puzzled, Jonathan
Well, this is from POSIX: http://pubs.opengroup.org/onlinepubs/9699919799/functions/system.html It is said: The system() function shall behave as if a child process were created using fork(), and the child process invoked the sh utility using execl() as follows: execl(<shell path>, "sh", "-c", command, (char *)0); where <shell path> is an unspecified pathname for the sh utility. It is unspecified whether the handlers registered with pthread_atfork() are called as part of the creation of the child process. The system() function shall ignore the SIGINT and SIGQUIT signals, and shall block the SIGCHLD signal, while waiting for the command to terminate. If this might cause the application to miss a signal that would have killed it, then the application should examine the return value from system() and take whatever action is appropriate to the application if the command terminated due to receipt of a signal. The rationale makes it clear about which process(es) shall ignore these signals: Ignoring SIGINT and SIGQUIT in the parent process prevents coordination problems (two processes reading from the same terminal, for example) when the executed command ignores or catches one of the signals. and from the example implementation, one can see that the previous actions are restored in the child, just before executing /bin/sh. This contradicts the glibc manual, which doesn't claim to do anything concerning signals in the system() implementation (and in some other discussion, it was said that glibc does only what is written):
Vincent Lefevre wrote: Ah, I should have remembered. That's the right behavior for system(), and it's what glibc does. (I'm afraid I have no interest in fixing the glibc manual, since its copyright holders have chosen to use an unpleasant license and stick to it and there is better documentation available elsewhere.) Thanks, Jonathan
Hi, this bug log now suggests that zsh is in the same boat and the bug possibly lies within emacs. Do you still think it's a release-critical bug in dash? Thanks, Gerrit.
spamcop is wrong.----- Forwarded message from MAILER-DAEMON@a.mx.smarden.org ----- Date: 28 Aug 2012 11:12:28 -0000 From: MAILER-DAEMON@a.mx.smarden.org Subject: failure notice Hi. This is the qmail-send program at a.mx.smarden.org. I'm afraid I wasn't able to deliver your message to the following addresses. This is a permanent error; I've given up. Sorry it didn't work out. <vincent@vinc17.net>: 92.243.22.117 does not like recipient. Remote host said: 554 5.7.1 Service unavailable; Client host [176.74.58.109] blocked using bl.spamcop.net; Blocked - see http://www.spamcop.net/bl.shtml?176.74.58.109 Giving up on 92.243.22.117.--- Below this line is a copy of the message. Received: (qmail 3983 invoked by uid 1000); 28 Aug 2012 11:05:45 -0000 Message-ID: <20120828110545.3982.qmail@818822b293fcc9.315fe32.mid.smarden.org> Date: Tue, 28 Aug 2012 11:05:45 +0000 From: Gerrit Pape <pape@smarden.org> To: Vincent Lefevre <vincent@vinc17.net>, 683671@bugs.debian.org Cc: Jonathan Nieder <jrnieder@gmail.com> Subject: Re: Bug#683671: dash doesn't ignore SIGINT when running an interactive command Reply-To: Vincent Lefevre <vincent@vinc17.net>, 683671@bugs.debian.org, Jonathan Nieder <jrnieder@gmail.com> References: <20120802170618.GA18343@ypig.lip.ens-lyon.fr> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20120802170618.GA18343@ypig.lip.ens-lyon.fr> Hi, this bug log now suggests that zsh is in the same boat and the bug possibly lies within emacs. Do you still think it's a release-critical bug in dash? Thanks, Gerrit.----- End forwarded message -----
Well, contrary to dash, zsh is not meant to be a POSIX shell, and cannot (must not) be used as /bin/sh (zsh has a sh emulation mode, but it is not perfect, and its status is quite unclear). This is one major point. However I think that any application that uses the INTR character for its own, internal purpose should put itself in its own process group to avoid side effects. But if developers don't agree, the problem must be dealt with in the shell. Note that http://pubs.opengroup.org/onlinepubs/9699919799/functions/system.html (see "Application Usage" and "Rationale") suggests that it's up to the callers (the system() implementation and, by extension, the sh implementation) to do the necessary to ignore signals when need be. The fact that dash implements WUE instead of IUE avoids the most important problems mentioned at the above URL, though. Moreover gdb has the same problem as Emacs, though problems are less likely to appear in practice than with Emacs (an editor is much more often called by system() than gdb). I think that the current status may badly affect the usual use of some applications like Emacs. The fact that there are, AFAIK, no workarounds (except by not using dash, e.g. by changing the /bin/sh symlink) makes me think that it should still be a RC bug.
Would you mind if this were reassigned to release-notes? It would say something along the lines of "Dash is not yet ready as an interactive shell, bash is currently the only recommended posix-compliant shell. You will experience issues such as #683671 using dash interactively." In the meantime, this should be reported to the upstream dash developers so they can start working on a fix. Best wishes, Mike
Would you mind if this were reassigned to release-notes? It would say something along the lines of "Dash is not yet ready as an interactive shell, bash is currently the only recommended posix-compliant shell. You will experience issues such as #683671 using dash interactively." In the meantime, this should be reported to the upstream dash developers so they can start working on a fix. Best wishes, Mike
Michael Gilbert wrote: I think that's an overstatement. Maybe "Dash in Debian is not intended to be used as an interactive shell" could be accurate, though. Please don't reassign this bug, but feel free to clone it and lower the severity. Thanks, Jonathan
Michael Gilbert wrote: I think that's an overstatement. Maybe "Dash in Debian is not intended to be used as an interactive shell" could be accurate, though. Please don't reassign this bug, but feel free to clone it and lower the severity. Thanks, Jonathan
The word "interactive" is incorrect, because when the shell is used to run some program (e.g. via C's system() function), it is not interactive. Yes, this is really a bug in dash IMHO, but Emacs is partly in fault because the Ctrl-G will also send the signal in the other processes in the same process group an Emacs (though this may not be very common). The current situation is extremely annoying. :(
[also sent to 683671@b.d.o since this concerns dash; for reportbug, one should do a test with bash as /bin/sh to see whether reportbug is really buggy or if this is just a consequence of the dash bug.] I couldn't try because the Debian BTS doesn't have a test system (due avoid creating a dummy bug report), but a Ctrl-C in Mutt also sends a SIGINT to the whole process group (as expected), even when one doesn't quit Mutt and Mutt terminates normally. So, even if the problem is "fixed" (avoided) in Emacs, the real problem still exists.
Control: severity -1 important I don't think this should be a blocker for release. Downgrading. Cheers, Julien
# hello, control, been a while... tag 683671 + patch fixed-upstream thanks Hi Andrej et al., After independently encountering and then debugging this problem to the point where I had a fix, I learned that Antonio Ospite had come up with an identical one (modulus whitespace) over a year ago[1]. I've attached a copy. It really sucks that dash has had this bug for 12 years, given that: 1. It's Debian's default /bin/sh; 2. We're required by Policy to 'set -e' in our maintainer scripts[2]; and 3. Script authors generally don't write signal handlers for fun--they do it because they need to clean up or roll back some activity, and this bug utterly frustrates their efforts. Were I active in the project, I'd be raising hell like in the old days to get this bug's severity back up to 'serious', on the premise that it frustrates the robustness of maintainer scripts that we try to ensure with 'set -e' in the first place. The fix is a transposition of one line; please consider applying it. I notice there are other fixes in the git repo, also usually from Antonio Ospite, for various compiler warnings. Those may be worthy of consideration in a near-term package release as well. Cheers! [1] https://git.kernel.org/pub/scm/utils/dash/dash.git/commit/?id=06204f0c9f539fcb8cb532166656e80b81bd689a [2] https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html
# hello, control, been a while... tag 683671 + patch fixed-upstream thanks Hi Andrej et al., After independently encountering and then debugging this problem to the point where I had a fix, I learned that Antonio Ospite had come up with an identical one (modulus whitespace) over a year ago[1]. I've attached a copy. It really sucks that dash has had this bug for 12 years, given that: 1. It's Debian's default /bin/sh; 2. We're required by Policy to 'set -e' in our maintainer scripts[2]; and 3. Script authors generally don't write signal handlers for fun--they do it because they need to clean up or roll back some activity, and this bug utterly frustrates their efforts. Were I active in the project, I'd be raising hell like in the old days to get this bug's severity back up to 'serious', on the premise that it frustrates the robustness of maintainer scripts that we try to ensure with 'set -e' in the first place. The fix is a transposition of one line; please consider applying it. I notice there are other fixes in the git repo, also usually from Antonio Ospite, for various compiler warnings. Those may be worthy of consideration in a near-term package release as well. Cheers! [1] https://git.kernel.org/pub/scm/utils/dash/dash.git/commit/?id=06204f0c9f539fcb8cb532166656e80b81bd689a [2] https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html
[...] I don't see the relation with bug 683671.
[...] I don't see the relation with bug 683671.
[...] I don't see the relation with bug 683671.
tag 683671 - patch fixed-upstream tag 779416 + patch fixed-upstream thanks Hi Vincent, Er, it appears that I misunderstood the discussion in the bug history. I had been fixing a bug where an INT signal handler improperly did not reraise INT against itself, and had Martin Cracauer's article on INT, QUIT and shell signal handlers[1] fresh in my brain. When I addressed the bad signal handler issue I was startled that dash did not behave according to my expectations. I prepared to file a bug against dash, and when scanning the existing bug list I found this one and, perhaps hastily, concluded that it was the same issue. Re-reviewing the list of open bugs against dash, it looks like I should have stumbled across #779416 instead. I apologize for my error. Thanks for the clarification. Cheers! [1] https://www.cons.org/cracauer/sigint.html [...] I don't see the relation with bug 683671.
Hello, is there any progress on this [bug]? Was it forwarded upstream? Are the upstream developers willing to fix it? [bug]: <https://bugs.debian.org/683671>
Please let me know, thanks for your time and understanding.
Hi, I can no longer reproduce the bug. I'm wondering whether there has been a change in Emacs or in dash...
Control: found -1 0.5.12-12 It seems to be Emacs. Here's another testcase (type Ctrl-C just after running the command): $ dash -c 'echo foo; bash -c "trap \"echo Interrupt; exit 0\" INT; sleep 5"'; echo OK foo ^CInterrupt $ bash -c 'echo foo; bash -c "trap \"echo Interrupt; exit 0\" INT; sleep 5"'; echo OK foo ^CInterrupt OK $ ksh93 -c 'echo foo; bash -c "trap \"echo Interrupt; exit 0\" INT; sleep 5"'; echo OK foo ^CInterrupt OK $ mksh -c 'echo foo; bash -c "trap \"echo Interrupt; exit 0\" INT; sleep 5"'; echo OK foo ^CInterrupt $ So dash still doesn't implement WCE. Ditto for mksh. FYI, the mksh Debian bug was closed because mksh upstream bugs are not tracked in Debian, and its upstream bug is https://bugs.launchpad.net/mksh/+bug/1064726 For dash, I don't know whether it has been reported upstream. According to its home page, there's just a mailing-list, and the archive website is broken: 503 Service Temporarily Unavailable