Avoid race condition with Popen.send_signal

Adam Skutt askutt at gmail.com
Tue Jan 3 09:12:59 EST 2012


On Jan 3, 3:44 am, Jérôme <jer... at jolimont.fr> wrote:
> Mon, 2 Jan 2012 19:16:50 -0800 (PST)
> Adam Skutt a écrit:
>
> > No. It is possible (however unlikely) for EPERM to be legitimately
> > returned in this case.  Anything other than EINVAL should be
> > interpreted as "The child process is dead".  Hence why you should
> > avoid sending the signal in the first place: the situations where you
> > don't run the risk of possibly killing an innocent bystander are
> > pretty narrow.  While unlikely on modern UNiX and Linux, IMO it's best
> > to avoid the issue altogether whenever possible.
>
> Should I understand that Popen.send_signal blindly sends the signal to the
> process of PID Popen.pid, and therefore could kill a new process of the same
> PID that would have been launched by the same user in another program ?
>

Or possibly one launched by another user altogether.  By /default/,
child processes that terminate become zombies and remain in that state
until their parent reaps them via wait(2) or a related syscall.  This
means that until you make such a call, the signal is delivered to the
desired child process.  In this case, kill(2) still returns ESRCH
since the child process is a zombie and cannot possibly respond to the
signal.

However, if SIGCHLD has been explicitly ignored or has no SA_NOCLDWAIT
set, child processes are reaped automatically.  Likewise, it is
possible to install a signal handler for SIGCHLD that calls wait and
reaps the child processes.  Do you know what all of your other Python
modules and extensions do? If so, then you can probably rely on the
default semantics.  If not, I'd strongly suggest a more conservative
approach.

Regardless, of whether you can rely on the presence of your zombie
children or not, you should expect the kill(2) call to fail and be
prepared to trap the failure.

Obviously, all of this is rather UNIX / Linux specific.

> If so, I don't see how I can protect myself from that. Checking the process
> is alive and then hoping that the time interval for the race condition is so
> small that there are few chances for that to happen (because the OS
> quarantines PID numbers for a while, for instance) ?

The conservative approach is to use another IPC mechanism to talk to
the process, such as a pipe or a socket.  Why are you trying to send
the child process SIGINT in the first place?

Adam



More information about the Python-list mailing list