Re: Bug in signalmodule.c + FIX (probably a hack :-)

lance@fox.com
Thu, 8 Sep 94 9:24:07 PDT

I can make some changes to fix this problem, but they will only
be valid on systems that conform to IEEE POSIX Std 1003.1-1990,
XPG3, NIST FIPS 151-1.

The way it would work is this:

Instead of using signal() I would use sigaction(). Once a signal
is raised, I would use sigprocmask() and SIG_BLOCK that signal before
resetting the sigaction(). Then when the signal is handled by the
python engine, I would sigprocmask()/SIG_UNBLOCK the signal and allow
further processing. The only change would be to the routine that
handles the SIGCHLD. It would have to call wait() until there were
no more children to process.

If this is ok with everyone else, I will also add sigsuspend(), sigpending()
and export the sigprocmask() functions in the signal module. I would
export the function of sigaction() and map the current call to signal()
into the correct sigaction() calls.

This should fix the problems, but I don't know what systems support
these routines.

> From: Guido.van.Rossum@cwi.nl
> Date: Thu, 08 Sep 1994 14:51:53 +0200
>
> Michael Scharf writes:
>
> > I got a problem with the signal module on IRIX5. I created the
> > server below (which is based on the example in the python
> > manual). When the parent gets the signal SIGCLD then the signal
> > module enters an infinite recursion...
>
> > I fixed it, but I did it blindly - I mean without understanding
> > what's going on. But this fix seems to solve the problem - at least
> > for me :-)
>
> Aha, I see the problem. This is because on System V, SIGCHLD (for
> which SIGCLD is just an alias) has very special semantics: it is
> raised whenever there's at least one waiting child and the signal is
> enabled. The Python signal module delays handling of all signals
> until the interpreter is ready for them by setting a flag and then
> re-instating the signal handler. This is a change compared to the
> System V C semantics: there, a signal's handler is reset to SIG_DFL
> and must explicitly re-caught by a call to signal(). The Python
> signal module attempts to mimic the BSD signal semantics where a
> signal setting remains in effect until explicitly reset.
>
> Unfortunately all this causes a recursion loop for SIGCHLD: when the
> handler (in C) sets the flag and re-instates the signal handler, the
> child has not yet been waited for so the signal is raised again
> immediately, causing recursion. Michael's fix stops recursive calls
> to the signal handler, but this means that the signal will not be
> handled again, until the Python code calls signal() again.
>
> I'm not sure what the best fix for this situation is.
>
> We can't call the Python handler from within the C handler for a
> variety of reasons (e.g. the Python interpreter could be in the middle
> of updating a mutable object).
>
> Changing to System V semantics (requiring the Python handler to
> re-instate the handler) for all signals has the problem that there is
> a window within which signals may be lost (between the moment the C
> handler returns and the Python handler re-instates the handler). (I
> assume that in System V, when a non-SIGCHLD signal occurs while the
> handler for it is still executing, the signal's delivery is delayed,
> so there is no window for C applications.)
>
> Waiting for the child in the C handler would require a complicated
> manoeuver to pass its exit status to Python.
>
> Maybe the best solution would be to make an exception for SIGCHLD, and
> use System V semantics (handlers must explicitly re-instate
> themselves) for this signal but BSD semantics (handlers remain in
> effect until explicitly reset) for all other signals.
>
> Question: would this solution break on BSD systems?
>
> --Guido van Rossum, CWI, Amsterdam <Guido.van.Rossum@cwi.nl>
> <URL:http://www.cwi.nl/cwi/people/Guido.van.Rossum.html>

--
Lance Ellinghouse                lance@fox.com