Re: [Chicken-users] replace signal with sigaction

From:

Alan Post

Subject:

Re: [Chicken-users] replace signal with sigaction

Date:

Thu, 29 Sep 2011 09:57:24 -0600

On Thu, Sep 29, 2011 at 05:45:46PM +0200, Jörg F. Wittenberger wrote:
> Here an interesting finding:
>
> On Sep 29 2011, Alan Post wrote:
>
> >This patch replaces signal with sigaction for registering signals.
> >sigaction is a newer API for signal processing that fixes some
> >deficiencies of the original signal API. One fix can be seen in
> >this patch: we don't have to reregister the signal handler after
> >a signal is sent.
> >
> >That prevents a race condition whereby a signal is delivered, our
> >signal handler is reset, and before we can reregister our signal
> >handler, another signal is sent (which we then miss).
>
> Since I'm quite old school I've been used to the meaning of signals
> to be "almost reliable". Except under arbitrary complex usage
> restrictions.
>
> Hence I rarely ever tried to count signals, but use them as a hint,
> which operation would be in order.
>
> This might have been not enough!
>
> Turn out that with your patch applied something changed:
> I had one usage case, which "almost sure" (say ~50%+-25%) would run
> into that eat-all-memory condition. I tried too often, I fail to
> reproduce the condition.
>
> However at this time I can't convince myself that this is not a false
> positive. :-/
>
Even with my patch, there is still a bug in the chicken signal
handler:
void global_signal_handler(int signum)
{
C_raise_interrupt(signal_mapping_table[ signum ]);
}
This signal handler will notify the main thread that signal X has
been raised, but it doesn't keep track of how often that happens.
By the time we get around to handling this signal, it could have
been raised more than once, and we only fire our signal handler
once regardless of how many signals were delivered between the
original interrupt and executing the deferred handler.
If you're doing anything at all that is reasonably interrupt
heavy, you're going to be seeing this behavior. The quick test
would be to fork a few hundred children (that all immediately
exit) all at once and count the number of times SIGCHLD is raised.
I haven't written this test yet, it's my next test case to follow
my EINTR test--though I suspect you'll get fewer SIGCHLD interrupts
than you had spawned children.
I also suspect there is a condition here where the signal handler
flags the interrupt to be raised, but we're already servicing the
deferred signal, and it goes ahead and resets the
signal_mapping_table before the signal currently being raised is
handled by deferral. If you're coping with unreliable delivery
from the above method, maybe you're seeing this case instead, which
would be a different class of behavior.
Rather than 1 or more deferred signals being delivered for N signals
raised, you might well see 0 under this condition--If this can happen
at all. I'm assuming it can, looking at the code, but haven't
verified yet.
-Alan
--
.i ma'a lo bradi cu penmi gi'e du