From: cjwatson <> Date: Thu, 2 Jul 2009 08:14:26 +0000 (+0000) Subject: Python SIGPIPE handling X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~cjwatson/git?a=commitdiff_plain;h=0a8cec877197ac2e85b9b334bed04815bbb83121;p=blog.git Python SIGPIPE handling --- diff --git a/2009-07-02-python-sigpipe.txt b/2009-07-02-python-sigpipe.txt new file mode 100644 index 00000000..af61ab97 --- /dev/null +++ b/2009-07-02-python-sigpipe.txt @@ -0,0 +1,37 @@ +Python SIGPIPE handling + +

Enrico +writes about creating pipelines with Python's subprocess +module, and notes that you need to take care to close stdout in non-final +subprocesses so that subprocesses get SIGPIPE correctly. This +is correct as far as it goes (and true in any language, although there's a +Python bug report requesting +that subprocess be able to do this itself), but there's an +additional gotcha with Python that you missed.

+ +

Python ignores SIGPIPE on startup, because it prefers to +check every write and raise an IOError exception rather than +taking the signal. This is all well and good for Python itself, but most +Unix subprocesses don't expect to work this way. Thus, when you are creating +subprocesses from Python, it is very important to set +SIGPIPE back to the default action. Before I realised this was +necessary, I wrote code that caused serious data loss due to a child process +carrying on out of control after its parent process died!

+ +
+import signal
+import subprocess
+
+def subprocess_setup():
+    # Python installs a SIGPIPE handler by default. This is usually not what
+    # non-Python subprocesses expect.
+    signal.signal(signal.SIGPIPE, signal.SIG_DFL)
+
+subprocess.Popen(command, preexec_fn=subprocess_setup)
+
+ +

I filed a patch a while +back to add a restore_sigpipe option to +subprocess.Popen, which would take care of this. As I say in +that bug report, in a future release I think this ought to be made the +default, as it's very easy to get things dangerously wrong right now.