[Python-Dev] Re: Signal-resistant code

Oren Tirosh oren-py-d@hishome.net
Fri, 6 Sep 2002 01:23:30 +0300

On Thu, Sep 05, 2002 at 04:46:27PM -0400, Guido van Rossum wrote:
> > > I admit that I hate signals so badly that whenever I needed to wait
> > > for a child to finish I would always structure the program around this
> > > need (even when coding in C).
> > 
> > Ummm... if you really hate signals that much perhaps you to step aside 
> > from this particular discussion? Naturally, you will get to pronounce on 
> > the results that come out of it (if any ;-)
> Why?  I don't think hating signals disqualifies me from understanding
> their problems.

In the past I have disqualified myself from making technical decisions on 
issues where I have been burned and knew that my opinion would be a calm
rational decision.

> I asked what the Python code called by the wrapper when a signal
> arrives is allowed to do (e.g. close the file?).  If you replied to
> that, I missed it.

Anything that a Python thread is allowed to do without grabbing a 
lock, i.e. anything that involves only exclusive resources or atomic 
Python operations on shared resources like setting a variable (but 
not read-modify-write). A signal handler is also allowed to raise an 
exception that will get delivered to the main thread.

> > If the system's libc wraps them it can be disabled by SA_RESTART
> > (posix) or siginterrupt (BSD).  On some systems read and recv return
> > a short buffer instead of EINTR.
> This latter sentence shows that you don't understand signals, or
> you're being very sloppy.  You get *either* a short buffer *or* EINTR
> depending on whether some data was already transferred to user space.

Did I say that you get *both* a short buffer *and* EINTR?  What I meant 
is that it's really quite simple - if errno==EINTR I retry and if I get 
a short buffer I continue from whatever I got and ask for the remainder
and this should work regardless of the differences in behavior between 
different systems, sockets and files, etc.

> > This can be safely ignored because it only happens for pipes and
> > sockets where this is a valid result. AFAIR it's guaranteed not to
> > happen on regular files so we won't be tricked into believing they
> > reached EOF.
> I don't believe that a short read on a regular file can be used
> reliably to infer EOF anyway.  The file could be growing while we read.

You're right, only a zero result on read should be interpreted as EOF,
not a short result. I got confused by fread where a short read does mark
an end of file condition.  I don't see how the growing file case is
relevant, though.

> > Three - Threads playing "who gets the signal".  The Python signal module
> > has a hack that appears to work on all relevant platform - ignore the
> > signal if getpid() isn't the main thread.
> Doesn't that make signals unreliable?  What if thread 4 has forked a
> child, and the child exist?  Won't the SIGCHLD be sent to thread 4?
> AFAIK there's no standard for this, or if there is, not all systems
> comply.

I've never actually tried this one. I just went by the comments in 
signalmodule.c which claim that this works for all cases of how different 
implementations deliver signals to threads. I guess that was a bit hasty.