Tue, 3 Jan 2012 19:58:57 +1100
Chris Angelico a écrit:
> On Tue, Jan 3, 2012 at 7:44 PM, Jérôme <[email protected]> wrote:
> > 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 probability is extremely small. PIDs are generally allocated
> sequentially, and obviously one won't be reallocated until the
> previous process has terminated. You're looking at a narrow window of
> opportunity between a check and an action; you don't really need to
> worry about PID reuse within that window, unless there's a particular
> reason to fear it (eg your process is very low priority, or there's a
> lot of "process spinning" happening). Under normal circumstances, you
> won't see a new process start up with the same PID for some time.
>
> (I can't make a statement on Python's module, though.)
Thanks for clarifying this.
(Out of curiosity, what would be the way to be sure when not in "normal
circumstances" ?)
So I rely on the OS for not allocating a "recently released" PID. However, if
the PID was released long ago, I still need to cover myself up as Popen won't
do it for me.
E.g.:
I have an application that can spawn a subprocess to play a beep. I want it
to kill the subprocess when exiting.
To do so, my close() method must
a/ Check if any subprocess has actually been launched (I store the Popen in
a variable called _beep_process. If Popen has not been called, the variable
is init to 0 and the call to send_signal will fail.)
b/ Check if the process is still alive using Popen.poll() and returncode
(otherwise, I might kill a new process)
c/ Catch the exception in case the process would be dead since the last
check (otherwise, I might get an error from send_signal)
It looks like this :
#####################################################################
# Close
#####################################################################
def _close (self, widget):
# If self._beep_process != 0, a subprocess was launched at some point
if (0 != self._beep_process):
print "process launched"
self._beep_process.poll()
# If process still alive
if (None == self._beep_process.returncode):
print "process stil alive"
# Send signal
try:
self._beep_process.send_signal(signal.SIGINT)
except OSError, e:
if e.errno == errno.ESRCH:
print "process just died"
pass # process already dead
else:
raise # something else wrong - raise exception
else:
print "signal sent"
# wait for process to complete
self._beep_process.wait()
else:
print "process already dead"
# Close application
Gtk.main_quit()
#####################################################################
I would have expected something shorter.
For instance, Popen.send_signal() should not be able to send a signal to a
subprocess that has already returned, should it ? Is there any good reason
for allowing it to do so ? If not, it would spare me check b/ in this example.
--
Jérôme
--
http://mail.python.org/mailman/listinfo/python-list