[Bug 189] ash behaves strangely on CTRL-C (does not exit but fills process table)

bugzilla at busybox.net bugzilla at busybox.net
Thu Mar 19 13:33:34 UTC 2009


--- Comment #9 from Denys Vlasenko <vda.linux at googlemail.com>  2009-03-19 13:33:33 UTC ---
(In reply to comment #8)
> The problem with intpending=1 and pendingsig!=0 is that in this case the CTRL-C
> is lost because dotrap() might be called before raise_interrupt() is called
> which ends in the same broken scenario described. You can easily see this when
> you follow these steps:
> (1) Modify the script to have an handler for USR1 which does just a "return 0".
> (2) Start the script.
> (3) Stop the script with CTRL-Z.
> (4) Send SIGUSR1 to the script.
> (5) Send SIGINT to the script _and_ the sleep command.
> (6) Continue the script with "fg".
> Now you'll see the broken behavior again. Same happens if (4) and (5) are
> interchanged.

Unfortunately, it does not happen to me. I will rely on you to do the testing.

> I tried to skip resetting gotsig[SIGINT-1] in dotrap() when sigpending is 1
> but this ends in a loop. But maybe you know how to do it better...

Earlier you said:

The broken case looks like this:
- SIGINT received
- onsig() is called
- dotrap() is called (dunno why) which resets gotsig[SIGINT - 1]
- raise_interrupt() is called
- SIGINT check fails because it was reset in dotrap()
- shell does NOT finish

In the new case (SIGUSR1 + SIGINT + ash patched to not set pendingsig on
SIGINT), calling dotrap() is no longer a mystery or wrong, it does need to be
called because of SIGUSR1. One thing we can do is to not clear gotsig[SIGINT -
1] in dotrap() if there is no handler for SIGINT, thus allowing
raise_interrupt() to see it.

But before you try this fix - can you investigate further how exactly ash
manages to duplicate itself?! Ok, raise_interrupt() gets confused and it falls
through into raise_exception(EXSIG); which longjmp()s somewhere. It is still
not clear how this leads to fork() and duplicate ash process... worth looking
into because it may be a separate bug.

After you found out how that happens, try the fix a-la this in dotrap():

        for (i = 1, q = gotsig; i < NSIG; i++, q++) {
                if (*q == 0)
                p = trap[i];
                /* non-trapped SIGINT is handled separately by raise_interrupt,
                 * don't upset it by resetting gotsig[SIGINT-1] */
                if (i == SIGINT && !p)
                *q = 0;
                if (!p)
                skip = evalstring(p, SKIPEVAL);

You can find it in hot-fix directory (diffed against 1.13.3):


Configure bugmail: https://bugs.busybox.net/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are on the CC list for the bug.

More information about the busybox-cvs mailing list