https://github.com/python/cpython/commit/46006a1b355f75d06c10e7b8086912c483b34487
commit: 46006a1b355f75d06c10e7b8086912c483b34487
branch: main
author: Stephen Hansen <[email protected]>
committer: gpshead <[email protected]>
date: 2024-12-15T11:53:22-08:00
summary:

gh-127586: properly restore blocked signals in resource_tracker.py (GH-127587)

* Correct pthread_sigmask in resource_tracker to restore old signals

Using SIG_UNBLOCK to remove blocked "ignored signals" may accidentally
cause side effects if the calling parent already had said signals
blocked to begin with and did not intend to unblock them when
creating a pool. Use SIG_SETMASK instead with the previous mask of
blocked signals to restore the original blocked set.

* Adding resource_tracker blocked signals test

Co-authored-by: Peter Bierma <[email protected]>
Co-authored-by: Gregory P. Smith <[email protected]>

files:
A Misc/NEWS.d/next/Library/2024-12-03-20-28-08.gh-issue-127586.zgotYF.rst
M Lib/multiprocessing/resource_tracker.py
M Lib/test/_test_multiprocessing.py

diff --git a/Lib/multiprocessing/resource_tracker.py 
b/Lib/multiprocessing/resource_tracker.py
index 20ddd9c50e3d88..90e036ae905afa 100644
--- a/Lib/multiprocessing/resource_tracker.py
+++ b/Lib/multiprocessing/resource_tracker.py
@@ -155,13 +155,14 @@ def ensure_running(self):
                 # that can make the child die before it registers signal 
handlers
                 # for SIGINT and SIGTERM. The mask is unregistered after 
spawning
                 # the child.
+                prev_sigmask = None
                 try:
                     if _HAVE_SIGMASK:
-                        signal.pthread_sigmask(signal.SIG_BLOCK, 
_IGNORED_SIGNALS)
+                        prev_sigmask = 
signal.pthread_sigmask(signal.SIG_BLOCK, _IGNORED_SIGNALS)
                     pid = util.spawnv_passfds(exe, args, fds_to_pass)
                 finally:
-                    if _HAVE_SIGMASK:
-                        signal.pthread_sigmask(signal.SIG_UNBLOCK, 
_IGNORED_SIGNALS)
+                    if prev_sigmask is not None:
+                        signal.pthread_sigmask(signal.SIG_SETMASK, 
prev_sigmask)
             except:
                 os.close(w)
                 raise
diff --git a/Lib/test/_test_multiprocessing.py 
b/Lib/test/_test_multiprocessing.py
index 80b08b8ac66899..01e92f0d8d6b30 100644
--- a/Lib/test/_test_multiprocessing.py
+++ b/Lib/test/_test_multiprocessing.py
@@ -6044,6 +6044,21 @@ def test_resource_tracker_exit_code(self):
                 self._test_resource_tracker_leak_resources(
                     cleanup=cleanup,
                 )
+    @unittest.skipUnless(hasattr(signal, "pthread_sigmask"), "pthread_sigmask 
is not available")
+    def test_resource_tracker_blocked_signals(self):
+        #
+        # gh-127586: Check that resource_tracker does not override blocked 
signals of caller.
+        #
+        from multiprocessing.resource_tracker import ResourceTracker
+        signals = {signal.SIGTERM, signal.SIGINT, signal.SIGUSR1}
+
+        for sig in signals:
+            signal.pthread_sigmask(signal.SIG_SETMASK, {sig})
+            self.assertEqual(signal.pthread_sigmask(signal.SIG_BLOCK, set()), 
{sig})
+            tracker = ResourceTracker()
+            tracker.ensure_running()
+            self.assertEqual(signal.pthread_sigmask(signal.SIG_BLOCK, set()), 
{sig})
+            tracker._stop()
 
 class TestSimpleQueue(unittest.TestCase):
 
diff --git 
a/Misc/NEWS.d/next/Library/2024-12-03-20-28-08.gh-issue-127586.zgotYF.rst 
b/Misc/NEWS.d/next/Library/2024-12-03-20-28-08.gh-issue-127586.zgotYF.rst
new file mode 100644
index 00000000000000..80217bd4a10503
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2024-12-03-20-28-08.gh-issue-127586.zgotYF.rst
@@ -0,0 +1,3 @@
+:class:`multiprocessing.pool.Pool` now properly restores blocked signal 
handlers
+of the parent thread when creating processes via either *spawn* or
+*forkserver*.

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]

Reply via email to