diff options
author | Matt Martz <matt@sivel.net> | 2021-04-05 15:51:12 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-04-05 15:51:12 +0200 |
commit | 33185c29abb266293f196da91a832d7d0a9eb90b (patch) | |
tree | c59080fcba791db063e4cccc736d5917028c3b7b | |
parent | Add ansible-test six constraint for Python 2.6. (diff) | |
download | ansible-33185c29abb266293f196da91a832d7d0a9eb90b.tar.xz ansible-33185c29abb266293f196da91a832d7d0a9eb90b.zip |
Implement workaround for stdout deadlock in multiprocessing shutdown (#74099)
-rw-r--r-- | changelogs/fragments/workerprocess-stdout-deadlock.yml | 3 | ||||
-rw-r--r-- | lib/ansible/executor/process/worker.py | 13 |
2 files changed, 16 insertions, 0 deletions
diff --git a/changelogs/fragments/workerprocess-stdout-deadlock.yml b/changelogs/fragments/workerprocess-stdout-deadlock.yml new file mode 100644 index 0000000000..8e7fed5d78 --- /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 df3db35e4a..983df45bca 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): ''' |