Reopen stdout/err on process fork

This helps avoid deadlocks (https://github.com/python/cpython/issues/91776).
This commit is contained in:
George Tsiamasiotis 2024-09-23 22:22:46 +03:00
parent f407776e9a
commit 0a11ed3781

View File

@ -2,6 +2,7 @@ import atexit
import logging import logging
import multiprocessing as mp import multiprocessing as mp
import os import os
import sys
import threading import threading
from collections import deque from collections import deque
from contextlib import AbstractContextManager, ContextDecorator from contextlib import AbstractContextManager, ContextDecorator
@ -68,6 +69,19 @@ class log_thread(AbstractContextManager, ContextDecorator):
self._stop_thread() self._stop_thread()
# When a multiprocessing.Process exits, python tries to flush stdout and stderr. However, if the
# process is created after a thread (for example a logging thread) is created and the process fork
# happens while an internal lock is held, the stdout/err flush can cause a deadlock.
#
# https://github.com/python/cpython/issues/91776
def reopen_std_streams():
sys.stdout = os.fdopen(1, "w")
sys.stderr = os.fdopen(2, "w")
os.register_at_fork(after_in_child=reopen_std_streams)
# based on https://codereview.stackexchange.com/a/17959 # based on https://codereview.stackexchange.com/a/17959
class LogPipe(threading.Thread): class LogPipe(threading.Thread):
def __init__(self, log_name: str): def __init__(self, log_name: str):