From f2dccb90e893df30c2b8bfc925dba80f6ceed6a7 Mon Sep 17 00:00:00 2001 From: Jonathan Oddy Date: Fri, 3 Aug 2018 17:35:34 +0100 Subject: [PATCH] Restore SIGPIPE handler to DFL on POpen Python sets the SIGPIPE handler to SIG_IGN. On execv() signal handlers are reset to their defaults, EXCEPT those that are SIG_IGN which are left ignored. In Python 3 subprocess.popen explicitly resets the SIGPIPE handler to SIG_DFL, but unfortunately in Python 2.7 it does not. This leads to subprocesses being executed with SIGPIPE ignored. This is often a problem with bash scripts which rely on SIGPIPE to terminate commands in a pipe, but can easily be a problem with other applications. This implements the Python 3 behaviour for Python 2.7 by using a preexec_fn. --- changelogs/fragments/restore_sigpipe_dfl.yml | 2 ++ lib/ansible/module_utils/basic.py | 7 +++++++ 2 files changed, 9 insertions(+) create mode 100644 changelogs/fragments/restore_sigpipe_dfl.yml diff --git a/changelogs/fragments/restore_sigpipe_dfl.yml b/changelogs/fragments/restore_sigpipe_dfl.yml new file mode 100644 index 00000000000..331bd6a5038 --- /dev/null +++ b/changelogs/fragments/restore_sigpipe_dfl.yml @@ -0,0 +1,2 @@ +bugfixes: + - Restore SIGPIPE to SIG_DFL when creating subprocesses to avoid it being ignored under Python 2. diff --git a/lib/ansible/module_utils/basic.py b/lib/ansible/module_utils/basic.py index 2a6c26b2d3b..d673c0f69b9 100644 --- a/lib/ansible/module_utils/basic.py +++ b/lib/ansible/module_utils/basic.py @@ -68,6 +68,7 @@ import locale import os import re import shlex +import signal import subprocess import sys import types @@ -2681,6 +2682,11 @@ class AnsibleModule(object): return self._clean + def _restore_signal_handlers(self): + # Reset SIGPIPE to SIG_DFL, otherwise in Python2.7 it gets ignored in subprocesses. + if PY2 and sys.platform != 'win32': + signal.signal(signal.SIGPIPE, signal.SIG_DFL) + def run_command(self, args, check_rc=False, close_fds=True, executable=None, data=None, binary_data=False, path_prefix=None, cwd=None, use_unsafe_shell=False, prompt_regex=None, environ_update=None, umask=None, encoding='utf-8', errors='surrogate_or_strict', expand_user_and_vars=True): @@ -2825,6 +2831,7 @@ class AnsibleModule(object): stdin=st_in, stdout=subprocess.PIPE, stderr=subprocess.PIPE, + preexec_fn=self._restore_signal_handlers, ) # store the pwd