[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[BUG] Bash not reacting to Ctrl-C

From: Oleg Nesterov
Subject: [BUG] Bash not reacting to Ctrl-C
Date: Tue, 8 Feb 2011 19:21:15 +0100
User-agent: Mutt/1.5.18 (2008-05-17)


We believe that the non-interactive bash doesn't handle CTRL-C
correctly, please look into the attached thread from lkml for
more details.

In short: bash incorrectly assumes that if it is interrupted
by ^C then the current foreground job should be killed by this
signal too. This doesn't work if the child exits normally, and
"WTERMSIG() == SIGINT" in set_job_status_and_cleanup() looks

As Ingo reports, sometimes the shell script can miss ^C. Say,

        $ ./bash -c 'while true; do /bin/true; done'

the 1st ^C does not get processed (needs 3-5 attempts on my machine).

Initially I thought that the code is just racy, but lets consider
another example:


        perl -we '$SIG{INT} = sub {exit}; sleep'

        echo "Hehe, I am going to sleep after ^C"
        sleep 100

it doesn't react to the 1st ^C, 100% reproducible. This does not look
right to me, but otoh I can't believe this was not noticed before.
So, perhaps, there is some rationality behind this behaviour?

I do not know. The "patch" below fixes the problems but most probably
it is not correct, I don't really understand this code.

In case you can't read "perl -e" above, it is more or less equal to

        void int_handler(int sig)

        int main(void)
                signal(SIGINT, int_handler);



--- bash-4.1/jobs.c~ctrlc_exit_race     2011-02-07 13:52:48.000000000 +0100
+++ bash-4.1/jobs.c     2011-02-07 13:55:30.000000000 +0100
@@ -3299,7 +3299,7 @@ set_job_status_and_cleanup (job)
         signals are sent to process groups) or via kill(2) to the foreground
         process by another process (or itself).  If the shell did receive the
         SIGINT, it needs to perform normal SIGINT processing. */
-      else if (wait_sigint_received && (WTERMSIG (child->status) == SIGINT) &&
+      else if (wait_sigint_received /*&& (WTERMSIG (child->status) == 
SIGINT)*/ &&
              IS_FOREGROUND (job) && IS_JOBCONTROL (job) == 0)
          int old_frozen;

Attachment: bash_ctrlc_bug.mbox
Description: Text document

reply via email to

[Prev in Thread] Current Thread [Next in Thread]