From 3bbf281b15866fc6aecdf8283bca696e5c646300 Mon Sep 17 00:00:00 2001 From: Thierry Carrez Date: Thu, 20 Sep 2012 14:42:53 +0200 Subject: [PATCH] Restore SIGPIPE default action for subprocesses Python ignores SIGPIPE on startup, because it prefers to check every write and raise an IOError exception rather than taking the signal. Most Unix subprocesses don't expect to work this way. This patch (adapted from Colin Watson's post at http://tinyurl.com/2a7mzh5) sets SIGPIPE back to the default action for quantum.agent.linux.utils.execute, quantum.common.utils.execute and quantum-rootwrap created subprocesses. Fixes bug 1053364 Change-Id: Ib805f1f8846c245b75a5ea64278c840b823c1fb2 --- bin/quantum-rootwrap | 8 ++++++++ quantum/agent/linux/utils.py | 8 ++++++++ quantum/common/utils.py | 8 ++++++++ 3 files changed, 24 insertions(+) diff --git a/bin/quantum-rootwrap b/bin/quantum-rootwrap index bb7fbc0d5..96939ae2f 100755 --- a/bin/quantum-rootwrap +++ b/bin/quantum-rootwrap @@ -38,6 +38,7 @@ import ConfigParser import os +import signal import subprocess import sys @@ -47,6 +48,12 @@ RC_NOCOMMAND = 98 RC_BADCONFIG = 97 +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) + + if __name__ == '__main__': # Split arguments, require at least a command execname = sys.argv.pop(0) @@ -84,6 +91,7 @@ if __name__ == '__main__': stdin=sys.stdin, stdout=sys.stdout, stderr=sys.stderr, + preexec_fn=_subprocess_setup, env=filtermatch.get_environment(userargs)) obj.wait() sys.exit(obj.returncode) diff --git a/quantum/agent/linux/utils.py b/quantum/agent/linux/utils.py index 70f09414f..e8f3b7167 100644 --- a/quantum/agent/linux/utils.py +++ b/quantum/agent/linux/utils.py @@ -21,6 +21,7 @@ import fcntl import logging import os import shlex +import signal import socket import struct @@ -30,6 +31,12 @@ from eventlet.green import subprocess LOG = logging.getLogger(__name__) +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) + + def execute(cmd, root_helper=None, process_input=None, addl_env=None, check_exit_code=True, return_stderr=False): if root_helper: @@ -42,6 +49,7 @@ def execute(cmd, root_helper=None, process_input=None, addl_env=None, env.update(addl_env) obj = subprocess.Popen(cmd, shell=False, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, + preexec_fn=_subprocess_setup, env=env) _stdout, _stderr = (process_input and diff --git a/quantum/common/utils.py b/quantum/common/utils.py index 3d6db076a..d76c2ae09 100644 --- a/quantum/common/utils.py +++ b/quantum/common/utils.py @@ -23,6 +23,7 @@ import logging import os +import signal import subprocess import uuid @@ -47,6 +48,12 @@ def boolize(subject): return subject +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) + + def execute(cmd, process_input=None, addl_env=None, check_exit_code=True): logging.debug("Running cmd: %s", cmd) env = os.environ.copy() @@ -54,6 +61,7 @@ def execute(cmd, process_input=None, addl_env=None, check_exit_code=True): env.update(addl_env) obj = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, + preexec_fn=_subprocess_setup, env=env) result = None if process_input is not None: