Re: Avoid race condition with Popen.send_signal

Discussion in 'Python' started by Cameron Simpson, Jan 3, 2012.

  1. On 02Jan2012 20:31, Devin Jeanpierre <> 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 <> DoD#743
    http://www.cskk.ezoshosting.com/cs/

    WHAT"S A ""K3WL D00D"" AND WH3R3 CAN 1 G3T S0M3!!!!!!!!!!!????????
    - Darren Embry
     
    Cameron Simpson, Jan 3, 2012
    #1
    1. Advertising

  2. Cameron Simpson

    Adam Skutt Guest

    On Jan 2, 8:44 pm, Cameron Simpson <> wrote:
    > On 02Jan2012 20:31, Devin Jeanpierre <> 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
     
    Adam Skutt, Jan 3, 2012
    #2
    1. Advertising

  3. On 02Jan2012 19:16, Adam Skutt <> wrote:
    | On Jan 2, 8:44 pm, Cameron Simpson <> wrote:
    | > On 02Jan2012 20:31, Devin Jeanpierre <> 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 <> DoD#743
    http://www.cskk.ezoshosting.com/cs/

    Death is life's way of telling you you've been fired. - R. Geis
     
    Cameron Simpson, Jan 3, 2012
    #3
  4. Cameron Simpson

    Jérôme Guest

    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
     
    Jérôme, Jan 3, 2012
    #4
  5. On Tue, Jan 3, 2012 at 7:44 PM, Jérôme <> 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 isso
    > 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
     
    Chris Angelico, Jan 3, 2012
    #5
  6. Cameron Simpson

    Jérôme Guest

    Tue, 3 Jan 2012 19:58:57 +1100
    Chris Angelico a écrit:

    > On Tue, Jan 3, 2012 at 7:44 PM, Jérôme <> 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
     
    Jérôme, Jan 3, 2012
    #6
  7. Cameron Simpson

    Adam Skutt Guest

    On Jan 3, 3:44 am, Jérôme <> 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 isso
    > 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
     
    Adam Skutt, Jan 3, 2012
    #7
  8. Cameron Simpson

    Adam Skutt Guest

    On Jan 3, 3:58 am, Chris Angelico <> wrote:
    > On Tue, Jan 3, 2012 at 7:44 PM, Jérôme <> 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
     
    Adam Skutt, Jan 3, 2012
    #8
  9. Cameron Simpson

    Adam Skutt Guest

    On Jan 2, 11:53 pm, Cameron Simpson <> wrote:
    > On 02Jan2012 19:16, Adam Skutt <> wrote:
    > | On Jan 2, 8:44 pm, Cameron Simpson <> wrote:
    > | > On 02Jan2012 20:31, Devin Jeanpierre <> wrote:
    > | > | > I think that catching the exception is probably the most Pythonicway.
    > | > |
    > | > | 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
     
    Adam Skutt, Jan 3, 2012
    #9
  10. Cameron Simpson

    Adam Skutt Guest

    On Jan 3, 4:38 am, Jérôme <> 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
     
    Adam Skutt, Jan 3, 2012
    #10
  11. Cameron Simpson

    Jérôme Guest

    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
     
    Jérôme, Jan 3, 2012
    #11
  12. Cameron Simpson

    Jérôme Guest

    Tue, 3 Jan 2012 07:03:08 -0800 (PST)
    Adam Skutt a écrit:

    > On Jan 3, 4:38 am, Jérôme <> 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
     
    Jérôme, Jan 3, 2012
    #12
  13. Cameron Simpson

    Jérôme Guest

    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
     
    Jérôme, Jan 3, 2012
    #13
  14. Cameron Simpson

    Adam Skutt Guest

    On Jan 3, 10:09 am, Jérôme <> 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
     
    Adam Skutt, Jan 3, 2012
    #14
  15. Cameron Simpson

    Jérôme Guest

    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
     
    Jérôme, Jan 3, 2012
    #15
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. jimjim

    race condition question

    jimjim, Nov 1, 2003, in forum: Java
    Replies:
    6
    Views:
    430
    jimjim
    Nov 2, 2003
  2. Replies:
    1
    Views:
    361
    Kevin Spencer
    Aug 7, 2006
  3. Replies:
    3
    Views:
    756
  4. Jérôme
    Replies:
    4
    Views:
    291
    Heiko Wundram
    Jan 3, 2012
  5. Guillaume Marcais

    net-ssh send_signal

    Guillaume Marcais, Oct 22, 2005, in forum: Ruby
    Replies:
    5
    Views:
    202
    Jamis Buck
    Oct 22, 2005
Loading...

Share This Page