churchyard / rpms / python38

Forked from rpms/python38 5 years ago
Clone
72bc3f4
From 583bb07116505dcc73c0fc4aa3c1cf5074f3522d Mon Sep 17 00:00:00 2001
72bc3f4
From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= <miro@hroncok.cz>
72bc3f4
Date: Fri, 2 Nov 2018 14:01:28 +0100
72bc3f4
Subject: [PATCH] Revert "bpo-6721: Hold logging locks across fork() (GH-4071)
72bc3f4
 (#9291)"
72bc3f4
72bc3f4
This reverts commit 3b699932e5ac3e76031bbb6d700fbea07492641d.
72bc3f4
---
72bc3f4
 Lib/logging/__init__.py  | 50 ------------------------------
72bc3f4
 Lib/test/test_logging.py | 67 ----------------------------------------
72bc3f4
 2 files changed, 117 deletions(-)
72bc3f4
72bc3f4
diff --git a/Lib/logging/__init__.py b/Lib/logging/__init__.py
72bc3f4
index 3ad2cc38f6..53780cd600 100644
72bc3f4
--- a/Lib/logging/__init__.py
72bc3f4
+++ b/Lib/logging/__init__.py
72bc3f4
@@ -225,55 +225,6 @@ def _releaseLock():
72bc3f4
     if _lock:
72bc3f4
         _lock.release()
72bc3f4
 
72bc3f4
-
72bc3f4
-# Prevent a held logging lock from blocking a child from logging.
72bc3f4
-
72bc3f4
-if not hasattr(os, 'register_at_fork'):  # Windows and friends.
72bc3f4
-    def _register_at_fork_acquire_release(instance):
72bc3f4
-        pass  # no-op when os.register_at_fork does not exist.
72bc3f4
-else:  # The os.register_at_fork API exists
72bc3f4
-    os.register_at_fork(before=_acquireLock,
72bc3f4
-                        after_in_child=_releaseLock,
72bc3f4
-                        after_in_parent=_releaseLock)
72bc3f4
-
72bc3f4
-    # A collection of instances with acquire and release methods (logging.Handler)
72bc3f4
-    # to be called before and after fork.  The weakref avoids us keeping discarded
72bc3f4
-    # Handler instances alive forever in case an odd program creates and destroys
72bc3f4
-    # many over its lifetime.
72bc3f4
-    _at_fork_acquire_release_weakset = weakref.WeakSet()
72bc3f4
-
72bc3f4
-
72bc3f4
-    def _register_at_fork_acquire_release(instance):
72bc3f4
-        # We put the instance itself in a single WeakSet as we MUST have only
72bc3f4
-        # one atomic weak ref. used by both before and after atfork calls to
72bc3f4
-        # guarantee matched pairs of acquire and release calls.
72bc3f4
-        _at_fork_acquire_release_weakset.add(instance)
72bc3f4
-
72bc3f4
-
72bc3f4
-    def _at_fork_weak_calls(method_name):
72bc3f4
-        for instance in _at_fork_acquire_release_weakset:
72bc3f4
-            method = getattr(instance, method_name)
72bc3f4
-            try:
72bc3f4
-                method()
72bc3f4
-            except Exception as err:
72bc3f4
-                # Similar to what PyErr_WriteUnraisable does.
72bc3f4
-                print("Ignoring exception from logging atfork", instance,
72bc3f4
-                      method_name, "method:", err, file=sys.stderr)
72bc3f4
-
72bc3f4
-
72bc3f4
-    def _before_at_fork_weak_calls():
72bc3f4
-        _at_fork_weak_calls('acquire')
72bc3f4
-
72bc3f4
-
72bc3f4
-    def _after_at_fork_weak_calls():
72bc3f4
-        _at_fork_weak_calls('release')
72bc3f4
-
72bc3f4
-
72bc3f4
-    os.register_at_fork(before=_before_at_fork_weak_calls,
72bc3f4
-                        after_in_child=_after_at_fork_weak_calls,
72bc3f4
-                        after_in_parent=_after_at_fork_weak_calls)
72bc3f4
-
72bc3f4
-
72bc3f4
 #---------------------------------------------------------------------------
72bc3f4
 #   The logging record
72bc3f4
 #---------------------------------------------------------------------------
72bc3f4
@@ -844,7 +795,6 @@ class Handler(Filterer):
72bc3f4
         Acquire a thread lock for serializing access to the underlying I/O.
72bc3f4
         """
72bc3f4
         self.lock = threading.RLock()
72bc3f4
-        _register_at_fork_acquire_release(self)
72bc3f4
 
72bc3f4
     def acquire(self):
72bc3f4
         """
72bc3f4
diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py
72bc3f4
index 1ea2967f5b..5d5eba7357 100644
72bc3f4
--- a/Lib/test/test_logging.py
72bc3f4
+++ b/Lib/test/test_logging.py
72bc3f4
@@ -35,7 +35,6 @@ import os
72bc3f4
 import queue
72bc3f4
 import random
72bc3f4
 import re
72bc3f4
-import signal
72bc3f4
 import socket
72bc3f4
 import struct
72bc3f4
 import sys
72bc3f4
@@ -667,72 +666,6 @@ class HandlerTest(BaseTest):
72bc3f4
                 if os.path.exists(fn):
72bc3f4
                     os.unlink(fn)
72bc3f4
 
72bc3f4
-    # The implementation relies on os.register_at_fork existing, but we test
72bc3f4
-    # based on os.fork existing because that is what users and this test use.
72bc3f4
-    # This helps ensure that when fork exists (the important concept) that the
72bc3f4
-    # register_at_fork mechanism is also present and used.
72bc3f4
-    @unittest.skipIf(not hasattr(os, 'fork'), 'Test requires os.fork().')
72bc3f4
-    def test_post_fork_child_no_deadlock(self):
72bc3f4
-        """Ensure forked child logging locks are not held; bpo-6721."""
72bc3f4
-        refed_h = logging.Handler()
72bc3f4
-        refed_h.name = 'because we need at least one for this test'
72bc3f4
-        self.assertGreater(len(logging._handlers), 0)
72bc3f4
-
72bc3f4
-        locks_held__ready_to_fork = threading.Event()
72bc3f4
-        fork_happened__release_locks_and_end_thread = threading.Event()
72bc3f4
-
72bc3f4
-        def lock_holder_thread_fn():
72bc3f4
-            logging._acquireLock()
72bc3f4
-            try:
72bc3f4
-                refed_h.acquire()
72bc3f4
-                try:
72bc3f4
-                    # Tell the main thread to do the fork.
72bc3f4
-                    locks_held__ready_to_fork.set()
72bc3f4
-
72bc3f4
-                    # If the deadlock bug exists, the fork will happen
72bc3f4
-                    # without dealing with the locks we hold, deadlocking
72bc3f4
-                    # the child.
72bc3f4
-
72bc3f4
-                    # Wait for a successful fork or an unreasonable amount of
72bc3f4
-                    # time before releasing our locks.  To avoid a timing based
72bc3f4
-                    # test we'd need communication from os.fork() as to when it
72bc3f4
-                    # has actually happened.  Given this is a regression test
72bc3f4
-                    # for a fixed issue, potentially less reliably detecting
72bc3f4
-                    # regression via timing is acceptable for simplicity.
72bc3f4
-                    # The test will always take at least this long. :(
72bc3f4
-                    fork_happened__release_locks_and_end_thread.wait(0.5)
72bc3f4
-                finally:
72bc3f4
-                    refed_h.release()
72bc3f4
-            finally:
72bc3f4
-                logging._releaseLock()
72bc3f4
-
72bc3f4
-        lock_holder_thread = threading.Thread(
72bc3f4
-                target=lock_holder_thread_fn,
72bc3f4
-                name='test_post_fork_child_no_deadlock lock holder')
72bc3f4
-        lock_holder_thread.start()
72bc3f4
-
72bc3f4
-        locks_held__ready_to_fork.wait()
72bc3f4
-        pid = os.fork()
72bc3f4
-        if pid == 0:  # Child.
72bc3f4
-            logging.error(r'Child process did not deadlock. \o/')
72bc3f4
-            os._exit(0)
72bc3f4
-        else:  # Parent.
72bc3f4
-            fork_happened__release_locks_and_end_thread.set()
72bc3f4
-            lock_holder_thread.join()
72bc3f4
-            start_time = time.monotonic()
72bc3f4
-            while True:
72bc3f4
-                waited_pid, status = os.waitpid(pid, os.WNOHANG)
72bc3f4
-                if waited_pid == pid:
72bc3f4
-                    break  # child process exited.
72bc3f4
-                if time.monotonic() - start_time > 7:
72bc3f4
-                    break  # so long? implies child deadlock.
72bc3f4
-                time.sleep(0.05)
72bc3f4
-            if waited_pid != pid:
72bc3f4
-                os.kill(pid, signal.SIGKILL)
72bc3f4
-                waited_pid, status = os.waitpid(pid, 0)
72bc3f4
-                self.fail("child process deadlocked.")
72bc3f4
-            self.assertEqual(status, 0, msg="child process error")
72bc3f4
-
72bc3f4
 
72bc3f4
 class BadStream(object):
72bc3f4
     def write(self, data):
72bc3f4
-- 
72bc3f4
2.19.1
72bc3f4