Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #18361 > unrolled thread
| Started by | Cameron Simpson <cs@zip.com.au> |
|---|---|
| First post | 2012-01-03 12:44 +1100 |
| Last post | 2012-01-03 18:25 +0100 |
| Articles | 15 — 4 participants |
Back to article view | Back to comp.lang.python
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
Re: Avoid race condition with Popen.send_signal Cameron Simpson <cs@zip.com.au> - 2012-01-03 12:44 +1100
Re: Avoid race condition with Popen.send_signal Adam Skutt <askutt@gmail.com> - 2012-01-02 19:16 -0800
Re: Avoid race condition with Popen.send_signal Cameron Simpson <cs@zip.com.au> - 2012-01-03 15:53 +1100
Re: Avoid race condition with Popen.send_signal Adam Skutt <askutt@gmail.com> - 2012-01-03 06:52 -0800
Re: Avoid race condition with Popen.send_signal Jérôme <jerome@jolimont.fr> - 2012-01-03 09:44 +0100
Re: Avoid race condition with Popen.send_signal Adam Skutt <askutt@gmail.com> - 2012-01-03 06:12 -0800
Re: Avoid race condition with Popen.send_signal Jérôme <jerome@jolimont.fr> - 2012-01-03 16:09 +0100
Re: Avoid race condition with Popen.send_signal Adam Skutt <askutt@gmail.com> - 2012-01-03 09:58 -0800
Re: Avoid race condition with Popen.send_signal Jérôme <jerome@jolimont.fr> - 2012-01-03 19:45 +0100
Re: Avoid race condition with Popen.send_signal Chris Angelico <rosuav@gmail.com> - 2012-01-03 19:58 +1100
Re: Avoid race condition with Popen.send_signal Adam Skutt <askutt@gmail.com> - 2012-01-03 06:20 -0800
Re: Avoid race condition with Popen.send_signal Jérôme <jerome@jolimont.fr> - 2012-01-03 10:38 +0100
Re: Avoid race condition with Popen.send_signal Adam Skutt <askutt@gmail.com> - 2012-01-03 07:03 -0800
Re: Avoid race condition with Popen.send_signal Jérôme <jerome@jolimont.fr> - 2012-01-03 17:24 +0100
Re: Avoid race condition with Popen.send_signal Jérôme <jerome@jolimont.fr> - 2012-01-03 18:25 +0100
| From | Cameron Simpson <cs@zip.com.au> |
|---|---|
| Date | 2012-01-03 12:44 +1100 |
| Subject | Re: Avoid race condition with Popen.send_signal |
| Message-ID | <mailman.4327.1325555666.27778.python-list@python.org> |
On 02Jan2012 20:31, Devin Jeanpierre <jeanpierreda@gmail.com> wrote:
| > I think that catching the exception is probably the most Pythonic way.
|
| It's the only correct way.
Indeed, but be precise - chek that it _is_ error 3, or more portably,
errno.ESRCH. POSIX probably mandates that that is a 3, but the symbol
should track the local system if it differs. Example:
import errno
...
try:
...signal...
except OSError, e:
if e.errno == errno.ESRCH:
pass # or maybe an info log message
else:
raise # something else wrong - raise exception anyway
Cheers,
--
Cameron Simpson <cs@zip.com.au> DoD#743
http://www.cskk.ezoshosting.com/cs/
WHAT"S A ""K3WL D00D"" AND WH3R3 CAN 1 G3T S0M3!!!!!!!!!!!????????
- Darren Embry
[toc] | [next] | [standalone]
| From | Adam Skutt <askutt@gmail.com> |
|---|---|
| Date | 2012-01-02 19:16 -0800 |
| Message-ID | <63817f2b-ccf8-4d7d-92a6-c1d622986d8a@j10g2000vbe.googlegroups.com> |
| In reply to | #18361 |
On Jan 2, 8:44 pm, Cameron Simpson <c...@zip.com.au> wrote: > On 02Jan2012 20:31, Devin Jeanpierre <jeanpierr...@gmail.com> wrote: > | > I think that catching the exception is probably the most Pythonic way. > | > | It's the only correct way. > > Indeed, but be precise - chek that it _is_ error 3, or more portably, > errno.ESRCH. POSIX probably mandates that that is a 3, but the symbol > should track the local system if it differs. Example: > 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. Adam
[toc] | [prev] | [next] | [standalone]
| From | Cameron Simpson <cs@zip.com.au> |
|---|---|
| Date | 2012-01-03 15:53 +1100 |
| Message-ID | <mailman.4329.1325566392.27778.python-list@python.org> |
| In reply to | #18367 |
On 02Jan2012 19:16, Adam Skutt <askutt@gmail.com> wrote: | On Jan 2, 8:44 pm, Cameron Simpson <c...@zip.com.au> wrote: | > On 02Jan2012 20:31, Devin Jeanpierre <jeanpierr...@gmail.com> wrote: | > | > I think that catching the exception is probably the most Pythonic way. | > | | > | It's the only correct way. | > | > Indeed, but be precise - chek that it _is_ error 3, or more portably, | > errno.ESRCH. POSIX probably mandates that that is a 3, but the symbol | > should track the local system if it differs. Example: | | 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". Sure. I was more taking the line: catch and accept only the specific errors you understand. Of course he can catch EPERM also. But any other variant should at the least generate a warning to stderr or a log - it is _unexpected_. I take your point that reraising the exception may be overkill for failed signal delivery (if that was your point). But I am arguing for being very careful about what you silently pass as an ok thing. | 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. Fair enough too. But sometimes you need to nail a rogue child. Cheers, -- Cameron Simpson <cs@zip.com.au> DoD#743 http://www.cskk.ezoshosting.com/cs/ Death is life's way of telling you you've been fired. - R. Geis
[toc] | [prev] | [next] | [standalone]
| From | Adam Skutt <askutt@gmail.com> |
|---|---|
| Date | 2012-01-03 06:52 -0800 |
| Message-ID | <f5c7af9a-8ee2-4dce-8ca7-a7c93d56628b@m4g2000vbc.googlegroups.com> |
| In reply to | #18370 |
On Jan 2, 11:53 pm, Cameron Simpson <c...@zip.com.au> wrote: > On 02Jan2012 19:16, Adam Skutt <ask...@gmail.com> wrote: > | On Jan 2, 8:44 pm, Cameron Simpson <c...@zip.com.au> wrote: > | > On 02Jan2012 20:31, Devin Jeanpierre <jeanpierr...@gmail.com> wrote: > | > | > I think that catching the exception is probably the most Pythonic way. > | > | > | > | It's the only correct way. > | > > | > Indeed, but be precise - chek that it _is_ error 3, or more portably, > | > errno.ESRCH. POSIX probably mandates that that is a 3, but the symbol > | > should track the local system if it differs. Example: > | > | 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". > > Sure. I was more taking the line: catch and accept only the specific > errors you understand. That advice really only applies when we have interfaces that don't fully define their exceptional conditions. That's not the case here. Though I should correct myself and note that EPERM can only occur if SIGCHLD is being handled in a non-default fashion. That being said, I'm not sure any error code should be treated differently from another here. > Of course he can catch EPERM also. But any other > variant should at the least generate a warning to stderr or a log > it is _unexpected_. Are they really unexpected though? Even if they are, what is logging an error going to gain anyone? Even crashing may not be helpful, especially given that there have been bugs in the past with the return codes from kill(2). Certainly, I'd be far more concerned about ensuring my code doesn't accidentally kill the wrong process than worrying about ensuring it handles the return code from kill(2) correctly. > I take your point that reraising the exception may be overkill for > failed signal delivery (if that was your point). But I am arguing for > being very careful about what you silently pass as an ok thing. > Trapping too few conditions is just as erroneous as trapping too many. This is especially true when dealing with UNIX system calls. The right behavior is frequently not as simple as it may appear, unfortunately. > | 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. > > Fair enough too. But sometimes you need to nail a rogue child. Even if I believed that were true, I wouldn't use SIGINT to do it. Adam
[toc] | [prev] | [next] | [standalone]
| From | Jérôme <jerome@jolimont.fr> |
|---|---|
| Date | 2012-01-03 09:44 +0100 |
| Message-ID | <mailman.4339.1325580095.27778.python-list@python.org> |
| In reply to | #18367 |
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 ? In other words, if a user launches my python program, which in its turn launches a subprocess of PID N, then the subprocess dies, then the same user launches a terminal that gets the same PID (N), what happens if my python program calls Popen.send_signal(SIGINT) ? Does it kill the terminal ? 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) ? -- Jérôme
[toc] | [prev] | [next] | [standalone]
| From | Adam Skutt <askutt@gmail.com> |
|---|---|
| Date | 2012-01-03 06:12 -0800 |
| Message-ID | <8614ceb1-f31f-4904-b2b9-6ef0d2bc7cdc@m20g2000vbf.googlegroups.com> |
| In reply to | #18385 |
On Jan 3, 3:44 am, Jérôme <jer...@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
[toc] | [prev] | [next] | [standalone]
| From | Jérôme <jerome@jolimont.fr> |
|---|---|
| Date | 2012-01-03 16:09 +0100 |
| Message-ID | <mailman.4355.1325603216.27778.python-list@python.org> |
| In reply to | #18408 |
Tue, 3 Jan 2012 06:12:59 -0800 (PST) Adam Skutt a écrit: > 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? Say, you've got an application that plays a sound for a few seconds, using an external program for that (beep, sox). If you close the application, you want the sound to stop as well. I don't know much about subprocess, not much more than what is in the tutorial : http://docs.python.org/library/subprocess.html (I don't know much about signalling either, I'm learning...) I naively thought kill() was the "normal" way. Then realized terminate() or even send_signal(SIGINT) would be softer. What would be a good approach, then ? Should I try something like this ? communicate(input="Ctrl+C") (I'd need to figure out how to write Ctrl+C...) Would that be cross-platform ? -- Jérôme
[toc] | [prev] | [next] | [standalone]
| From | Adam Skutt <askutt@gmail.com> |
|---|---|
| Date | 2012-01-03 09:58 -0800 |
| Message-ID | <f6cd8985-1d8d-487d-9f5f-02d4b9a42e8e@t16g2000vba.googlegroups.com> |
| In reply to | #18412 |
On Jan 3, 10:09 am, Jérôme <jer...@jolimont.fr> wrote: > Tue, 3 Jan 2012 06:12:59 -0800 (PST) > Adam Skutt a écrit: > > > 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? > > Say, you've got an application that plays a sound for a few seconds, using an > external program for that (beep, sox). If you close the application, you want > the sound to stop as well. If your application wants to play audio and terminate playing audio early, it really should use an audio library and play the sound directly. Especially if you're playing so many sounds in such a fashion you need to terminate them. If you're playing a single beep or short sound, then who really cares if it occurs slightly after your processes ends? GStreamer is one such library for sound processing though it may be more complicated than you need. > Should I try something like this ? > > communicate(input="Ctrl+C") > > (I'd need to figure out how to write Ctrl+C...) > > Would that be cross-platform ? > No, that won't work at all. 'Ctrl-C' is a magic indicator to the terminal driver to send SIGINT to the appropriate processes: it never actually appears as an input and output character to a program unless it's controlling the terminal in raw mode (where it loses its special meaning). If you're really insistent on using the sox(1) command-line tools to play your sounds, then you'll have to send SIGINT or SIGTERM in order to tell it to terminate (which can be done just by calling the terminate() method). Which is fine and will probably work OK subject to three restrictions: 1. Nothing in your application modifies the default handling of SIGCHLD. This means that the child process appears as a zombie (e.g., via 'ps ax') until the parent calls poll() or wait() methods to reap it. 2. You only send signals while the process is alive or a zombie: once the poll() or wait() methods return something other than None, you cannot safely send anymore signals. 3. You trap any errors returned by the send signal call. Adam
[toc] | [prev] | [next] | [standalone]
| From | Jérôme <jerome@jolimont.fr> |
|---|---|
| Date | 2012-01-03 19:45 +0100 |
| Message-ID | <mailman.4365.1325616193.27778.python-list@python.org> |
| In reply to | #18425 |
Tue, 3 Jan 2012 09:58:35 -0800 (PST) Adam Skutt a écrit: > If you're really insistent on using the sox(1) command-line tools to play > your sounds, then you'll have to send SIGINT or SIGTERM in order to tell it > to terminate (which can be done just by calling the terminate() method). > > Which is fine and will probably work OK subject to three restrictions: > 1. Nothing in your application modifies the default handling of > SIGCHLD. This means that the child process appears as a zombie (e.g., > via 'ps ax') until the parent calls poll() or wait() methods to reap > it. > 2. You only send signals while the process is alive or a zombie: once > the poll() or wait() methods return something other than None, you > cannot safely send anymore signals. > 3. You trap any errors returned by the send signal call. Thank you very much for your patient explanations. I sort of figured that out from your precedent messages and I was writing the following : ----------------------------------------------------------------------- I use poll() in idle task to follow the process's activity, then set a variable if still in progress. If I do the signalling in idle task as well, relying on that variable, there should not be any race condition collateral damage. (If I did not, however, I could send SIGINT between poll() and the variable being set.) It just makes the code even heavier with each "stop sound" callback calling GObject.idle_add() to ask for the work to be done in idle task, instead of doing it right away. ----------------------------------------------------------------------- I agree with the fact that ideally I would use another playback library. The reason of my choice is "historical". This is my first python application. I started simple and used beep for simplicity. Then, as I wanted to use the sound card, I searched for a library (I posted here about that) and realized playing a sine wave was not that straightforward. (I tried alsaaudio and had multithreading issues (posted here as well).) As it was not that important to me (after all, it's just an exercise), I decided to move on and use sox, as invoking it would be quite similar to calling beep and I had already enough difficulties to face and other priorities. I guess I can always change my mind and use an audio library some day but I was merely interested in the way signalling and processes work. Thanks again. -- Jérôme
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2012-01-03 19:58 +1100 |
| Message-ID | <mailman.4341.1325581146.27778.python-list@python.org> |
| In reply to | #18367 |
On Tue, Jan 3, 2012 at 7:44 PM, Jérôme <jerome@jolimont.fr> 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.) ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Adam Skutt <askutt@gmail.com> |
|---|---|
| Date | 2012-01-03 06:20 -0800 |
| Message-ID | <70871926-8a1e-4506-b867-cde96537dcd9@m4g2000vbc.googlegroups.com> |
| In reply to | #18388 |
On Jan 3, 3:58 am, Chris Angelico <ros...@gmail.com> wrote: > On Tue, Jan 3, 2012 at 7:44 PM, Jérôme <jer...@jolimont.fr> 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. > Not all operating systems attempt to generate sequential processes IDs. The window can be rather large in certain situations, and if you cannot rely on your child processes becoming zombies and kill being called only when the child is alive or a zombie, then you should not be calling kill(2) at all. Killing an unrelated process will be considered as a bug by users. Hence why I find it easier just to avoid the problem altogether if I can. Adam
[toc] | [prev] | [next] | [standalone]
| From | Jérôme <jerome@jolimont.fr> |
|---|---|
| Date | 2012-01-03 10:38 +0100 |
| Message-ID | <mailman.4342.1325583331.27778.python-list@python.org> |
| In reply to | #18367 |
Tue, 3 Jan 2012 19:58:57 +1100
Chris Angelico a écrit:
> On Tue, Jan 3, 2012 at 7:44 PM, Jérôme <jerome@jolimont.fr> 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
[toc] | [prev] | [next] | [standalone]
| From | Adam Skutt <askutt@gmail.com> |
|---|---|
| Date | 2012-01-03 07:03 -0800 |
| Message-ID | <f677dfce-e286-4366-ba64-3585dc6428c7@p4g2000vbt.googlegroups.com> |
| In reply to | #18389 |
On Jan 3, 4:38 am, Jérôme <jer...@jolimont.fr> wrote: > I have an application that can spawn a subprocess to play a beep. I want it > to kill the subprocess when exiting. Why? You shouldn't need to send a signal to tell the process to terminate: it should terminate when its stdin is closed or when it's done playing the beep in the first place. If it doesn't, I would find a better way to play a beep in the first place. What you're attempting to do sounds superfluous and unnecessary. The only thing you ought to need to do is ensure that the child process is properly reaped if it terminates before your process terminates. > 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) > Steps a and c are all that are necessary under standard SIGCHLD handling. However, all of this should be entirely unnecessary in the first place. Plus, I have a hard time imagining why something like 'gtk.gdk.beep()' isn't adequate for your needs anyway. > 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. > The problem is being able to distinguish "process is a zombie" from "process doesn't exist" which both return ESRCH. This is certainly possible with careful coding but I'm not sure I would bother except in the simplest programs. Too many libraries do too many questionable things with signal handlers so I find it much safer and easier just to avoid the damn things whenever possible. Adam
[toc] | [prev] | [next] | [standalone]
| From | Jérôme <jerome@jolimont.fr> |
|---|---|
| Date | 2012-01-03 17:24 +0100 |
| Message-ID | <mailman.4357.1325607722.27778.python-list@python.org> |
| In reply to | #18416 |
Tue, 3 Jan 2012 07:03:08 -0800 (PST)
Adam Skutt a écrit:
> On Jan 3, 4:38 am, Jérôme <jer...@jolimont.fr> wrote:
> > I have an application that can spawn a subprocess to play a beep. I want
> > it to kill the subprocess when exiting.
>
> Why? You shouldn't need to send a signal to tell the process to
> terminate: it should terminate when its stdin is closed or when it's
> done playing the beep in the first place. If it doesn't, I would find
> a better way to play a beep in the first place. What you're
> attempting to do sounds superfluous and unnecessary.
Probably. And somehow, I'd be glad.
Once the command (say beep) is called, it does terminate when done with the
beep. I just don't know if it can be stopped while playing and how.
(Perhaps the only clean way would be to call it several times by period of
10ms, for instance, to be able to stop at any time. But this makes the whole
thing much more complicated.)
> The only thing you ought to need to do is ensure that the child
> process is properly reaped if it terminates before your process
> terminates.
The application polls the ongoing child process until it has terminated, and
fetches its returncode. I hope this is "proper reaping".
The tutorial (http://docs.python.org/library/subprocess.html) didn't suggest
me to do anything more than that.
> Steps a and c are all that are necessary under standard SIGCHLD
> handling. However, all of this should be entirely unnecessary in the
> first place.
That's good news, because it seems a little bit ugly.
> Plus, I have a hard time imagining why something like 'gtk.gdk.beep()'
> isn't adequate for your needs anyway.
Short answer : I may well be, I just didn't know it.
I just looked at it quickly and it does not seem as flexible. Besides, beep
is just an example, I also use sox. And anyway, the whole thing is just a
training exercise I'm inflicting on myself, so I'm interested in solving the
subprocess issue for itself.
> The problem is being able to distinguish "process is a zombie" from
> "process doesn't exist" which both return ESRCH. This is certainly
> possible with careful coding but I'm not sure I would bother except in
> the simplest programs. Too many libraries do too many questionable
> things with signal handlers so I find it much safer and easier just to
> avoid the damn things whenever possible.
My small program _seems to_ work with the dirty hacks I already exposed. Yet,
I'd rather stay on the safe and easy side, especially in a future bigger
program. Therefore, I'm still interested in a better way to proceed.
Is there another way to tell beep (or sox) to stop before the end of the
beep ?
AFAIK, the only way to stop it on console is to feed it Ctrl+C. Should I use
communicate() for that ? How ? Apparently, the following does not work :
process.communicate("\C-c")
It may well be that the dirtyness of my program comes from the choice of
external applications that don't allow nice termination through stdin. Or
perhaps is it possible and I haven't figured out how yet...
--
Jérôme
[toc] | [prev] | [next] | [standalone]
| From | Jérôme <jerome@jolimont.fr> |
|---|---|
| Date | 2012-01-03 18:25 +0100 |
| Message-ID | <mailman.4358.1325611385.27778.python-list@python.org> |
| In reply to | #18416 |
Tue, 3 Jan 2012 17:24:44 +0100
Jérôme a écrit:
> > Too many libraries do too many questionable things with signal handlers
> > so I find it much safer and easier just to avoid the damn things whenever
> > possible.
>
> My small program _seems to_ work with the dirty hacks I already exposed.
> Yet, I'd rather stay on the safe and easy side, especially in a future
> bigger program. Therefore, I'm still interested in a better way to proceed.
>
> Is there another way to tell beep (or sox) to stop before the end of the
> beep ?
>
> AFAIK, the only way to stop it on console is to feed it Ctrl+C. Should I use
> communicate() for that ? How ? Apparently, the following does not work :
>
> process.communicate("\C-c")
>
I've been reading more and what I wrote now appears to me as silly, as
Ctrl+C, as I understand, is just a way to send SIGINT...
I guess I'll have to do with the signal handling, then.
But I think I'm beggining to understand what you (Adam Skutt) meant. This is
just as dirty as using Ctrl+C to stop beep when using the console, as opposed
to using a software that would wait for a specific keypress to stop (in which
case I could use communicate()).
--
Jérôme
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.python
csiph-web