On Sep 30, 9:08 am, David <wizza...@gmail.com> wrote: > On Wed, Sep 29, 2010 at 6:49 PM, John Nagle <na...@animats.com> wrote: > > Python's signal handling for multithread and multiprocess programs > > leaves something to be desired. > > Thanks for the confirmation (that I'm not missing something obvious). > > I've reported a bug for this behavior in the Python issue tracker. > > In the meanwhile, I've made a workaround function called > "check_call_and_monitor_ppids", that behaves like > subprocess.check_call, except that it regularly checks if the parent > pid "chain" (up to init process) changes during execution, and then > terminates the subprocess and raises an exception. > > Actually I tried this before, and it didn't work. But strangely, it > seems to work fine so long as I don't try to print any warning > messages to stderr or stdout from the Python script (though, the > called tool itself may print to stdout or stderr without problems). > Quite peculiar... > > Anyway, I hope that one of the Python developers will fix this sometime. > > David.
Python ignores SIGPIPE by default. The default SIGPIPE behavior is to exit. This is sort of what people on POSIX expect. If you're talking to another process over a pipe and that process goes away, and then you write to the pipe, you get a SIGPIPE and you exit (of course, if it takes you 20 minutes before you do another write, then it's 20 minutes before you exit). But with SIGPIPE ignored, a Python process won't do exactly this. Instead, you'll get an exception from the write. If you don't handle the exception, then it'll propagate to the top-level and you'll exit. Just like with a "normal" process. Except you also get the option to doing something other than exiting. Pretty nice. But signal dispositions are inherited by child processes. So you run ping from your short Python program, and it inherits SIGPIPE being ignored. And it's written in C, not Python, so when it writes to the pipe, there's no exception. So ping never gets any indication that it should exit. No Python writes ever happen in this scenario. The SSH supplied stdout is shared with the ping process, which writes to it directly. You can fix this by resetting the signal disposition of SIGPIPE for the ping process: #!/usr/bin/python import signal def reset(): signal.signal(signal.SIGPIPE, signal.SIG_DFL) from subprocess import check_call check_call(['ping', 'www.google.com'], preexec_fn=reset) Very likely the subprocess module should be resetting the disposition of signals that Python itself has fiddled with (and resetting any other unusual state that the child is going to inherit, but nothing else comes immediately to mind). -- http://mail.python.org/mailman/listinfo/python-list