From 33185c29abb266293f196da91a832d7d0a9eb90b Mon Sep 17 00:00:00 2001 From: Matt Martz Date: Mon, 5 Apr 2021 08:51:12 -0500 Subject: [PATCH] Implement workaround for stdout deadlock in multiprocessing shutdown (#74099) --- .../fragments/workerprocess-stdout-deadlock.yml | 3 +++ lib/ansible/executor/process/worker.py | 13 +++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 changelogs/fragments/workerprocess-stdout-deadlock.yml diff --git a/changelogs/fragments/workerprocess-stdout-deadlock.yml b/changelogs/fragments/workerprocess-stdout-deadlock.yml new file mode 100644 index 00000000000..8e7fed5d782 --- /dev/null +++ b/changelogs/fragments/workerprocess-stdout-deadlock.yml @@ -0,0 +1,3 @@ +bugfixes: +- WorkerProcess - Implement workaround for stdout deadlock in multiprocessing shutdown + to avoid process hangs. diff --git a/lib/ansible/executor/process/worker.py b/lib/ansible/executor/process/worker.py index df3db35e4a6..983df45bca2 100644 --- a/lib/ansible/executor/process/worker.py +++ b/lib/ansible/executor/process/worker.py @@ -134,6 +134,19 @@ class WorkerProcess(multiprocessing_context.Process): return self._run() except BaseException as e: self._hard_exit(e) + finally: + # This is a hack, pure and simple, to work around a potential deadlock + # in ``multiprocessing.Process`` when flushing stdout/stderr during process + # shutdown. We have various ``Display`` calls that may fire from a fork + # so we cannot do this early. Instead, this happens at the very end + # to avoid that deadlock, by simply side stepping it. This should not be + # treated as a long term fix. Additionally this behavior only presents itself + # on Python3. Python2 does not exhibit the deadlock behavior. + # TODO: Evaluate overhauling ``Display`` to not write directly to stdout + # and evaluate migrating away from the ``fork`` multiprocessing start method. + if sys.version_info[0] >= 3: + sys.stdout = os.devnull + sys.stderr = os.devnull def _run(self): '''