From bf84e10d84ceedd361d40df48241072e486283fe Mon Sep 17 00:00:00 2001 From: Pierre Glaser Date: Tue, 19 Mar 2019 17:36:39 +0100 Subject: [PATCH 01/11] FIX protect shared_memory server from SIGINT --- Lib/multiprocessing/managers.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Lib/multiprocessing/managers.py b/Lib/multiprocessing/managers.py index 22abd47fb1f23f..2bad636855fe62 100644 --- a/Lib/multiprocessing/managers.py +++ b/Lib/multiprocessing/managers.py @@ -17,6 +17,7 @@ import sys import threading +import signal import array import queue import time @@ -596,6 +597,9 @@ def _run_server(cls, registry, address, authkey, serializer, writer, ''' Create a server, report its address and run it ''' + # bpo-36368: protect server process from KeyboardInterrupt signals + signal.signal(signal.SIGINT, signal.SIG_IGN) + if initializer is not None: initializer(*initargs) From d861f468e4c3ced2a03e705804573896e991d43f Mon Sep 17 00:00:00 2001 From: Pierre Glaser Date: Thu, 21 Mar 2019 15:57:12 +0100 Subject: [PATCH 02/11] TST test SharedMemoryManager after KeyboardInterrupt --- Lib/test/_test_multiprocessing.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py index 836fde88cd266d..6eab24a284a594 100644 --- a/Lib/test/_test_multiprocessing.py +++ b/Lib/test/_test_multiprocessing.py @@ -3734,6 +3734,21 @@ def test_shared_memory_across_processes(self): sms.close() + def test_shared_memory_SharedMemoryServer_ignores_sigint(self): + # bpo-36368: procect SharedMemoryManager server process from + # KeyboardInterrupt signals. + smm = multiprocessing.managers.SharedMemoryManager() + smm.start() + + # make sure the manager works properly at the beginning + sl = smm.ShareableList(range(10)) + sl.shm.unlink() + + # the manager's server should ignore SIGINT (<-KeyboardInterrupt) + # signals, and maintain its connection with the current process + os.kill(smm._process.pid, signal.SIGINT) + sl2 = smm.ShareableList(range(10)) + def test_shared_memory_SharedMemoryManager_basics(self): smm1 = multiprocessing.managers.SharedMemoryManager() with self.assertRaises(ValueError): From 2525a4b11d6ee45a269522632a6dc7c0b584bd0f Mon Sep 17 00:00:00 2001 From: Pierre Glaser Date: Thu, 21 Mar 2019 16:03:05 +0100 Subject: [PATCH 03/11] MNT news section --- .../NEWS.d/next/Library/2019-03-21-16-00-00.bpo-36368.zsRT1.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2019-03-21-16-00-00.bpo-36368.zsRT1.rst diff --git a/Misc/NEWS.d/next/Library/2019-03-21-16-00-00.bpo-36368.zsRT1.rst b/Misc/NEWS.d/next/Library/2019-03-21-16-00-00.bpo-36368.zsRT1.rst new file mode 100644 index 00000000000000..d8426827cedf04 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-03-21-16-00-00.bpo-36368.zsRT1.rst @@ -0,0 +1,2 @@ +Fix a bug crashing SharedMemoryManager instances in interactive sessions after +a ctrl-c (KeyboardInterrupt) was sent From 0987b23010180db023815a08422138bb5f34f178 Mon Sep 17 00:00:00 2001 From: Pierre Glaser Date: Thu, 21 Mar 2019 16:15:27 +0100 Subject: [PATCH 04/11] CLN typo --- Lib/test/_test_multiprocessing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py index 6eab24a284a594..c0d8f8266feb0e 100644 --- a/Lib/test/_test_multiprocessing.py +++ b/Lib/test/_test_multiprocessing.py @@ -3735,7 +3735,7 @@ def test_shared_memory_across_processes(self): sms.close() def test_shared_memory_SharedMemoryServer_ignores_sigint(self): - # bpo-36368: procect SharedMemoryManager server process from + # bpo-36368: protect SharedMemoryManager server process from # KeyboardInterrupt signals. smm = multiprocessing.managers.SharedMemoryManager() smm.start() From 7fa69e9337c39f323904a2c21d94876e48f5a51f Mon Sep 17 00:00:00 2001 From: Pierre Glaser Date: Thu, 21 Mar 2019 16:28:50 +0100 Subject: [PATCH 05/11] CLN remove unnecessary unlink command --- Lib/test/_test_multiprocessing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py index c0d8f8266feb0e..8e526d48a93f12 100644 --- a/Lib/test/_test_multiprocessing.py +++ b/Lib/test/_test_multiprocessing.py @@ -3742,12 +3742,12 @@ def test_shared_memory_SharedMemoryServer_ignores_sigint(self): # make sure the manager works properly at the beginning sl = smm.ShareableList(range(10)) - sl.shm.unlink() # the manager's server should ignore SIGINT (<-KeyboardInterrupt) # signals, and maintain its connection with the current process os.kill(smm._process.pid, signal.SIGINT) sl2 = smm.ShareableList(range(10)) + smm.shutdown() def test_shared_memory_SharedMemoryManager_basics(self): smm1 = multiprocessing.managers.SharedMemoryManager() From e3aa9c5e8a4b390f17bb071d16afcbc92c1d5bab Mon Sep 17 00:00:00 2001 From: Pierre Glaser Date: Thu, 21 Mar 2019 17:37:07 +0100 Subject: [PATCH 06/11] FIX handle correct interruption signal in windows --- Lib/multiprocessing/managers.py | 5 ++++- Lib/test/_test_multiprocessing.py | 10 +++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/Lib/multiprocessing/managers.py b/Lib/multiprocessing/managers.py index 2bad636855fe62..0577908c425469 100644 --- a/Lib/multiprocessing/managers.py +++ b/Lib/multiprocessing/managers.py @@ -598,7 +598,10 @@ def _run_server(cls, registry, address, authkey, serializer, writer, Create a server, report its address and run it ''' # bpo-36368: protect server process from KeyboardInterrupt signals - signal.signal(signal.SIGINT, signal.SIG_IGN) + if sys.platform != 'win32': + signal.signal(signal.SIGINT, signal.SIG_IGN) + else: + signal.signal(signal.CTRL_C_EVENT, signal.SIG_IGN) if initializer is not None: initializer(*initargs) diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py index 8e526d48a93f12..f7709c77096486 100644 --- a/Lib/test/_test_multiprocessing.py +++ b/Lib/test/_test_multiprocessing.py @@ -3743,9 +3743,13 @@ def test_shared_memory_SharedMemoryServer_ignores_sigint(self): # make sure the manager works properly at the beginning sl = smm.ShareableList(range(10)) - # the manager's server should ignore SIGINT (<-KeyboardInterrupt) - # signals, and maintain its connection with the current process - os.kill(smm._process.pid, signal.SIGINT) + # the manager's server should ignore KeyboardInterrupt signals, and + # maintain its connection with the current process + if sys.platform != 'win32': + os.kill(smm._process.pid, signal.SIGINT) + else: + os.kill(smm._process.pid, signal.CTRL_C_EVENT) + sl2 = smm.ShareableList(range(10)) smm.shutdown() From 10892dc39a1be249bd635ae0b139f3a18f77466f Mon Sep 17 00:00:00 2001 From: Pierre Glaser Date: Fri, 22 Mar 2019 17:04:18 +0100 Subject: [PATCH 07/11] FIX skip test on windows --- Lib/multiprocessing/managers.py | 5 +---- Lib/test/_test_multiprocessing.py | 6 ++---- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/Lib/multiprocessing/managers.py b/Lib/multiprocessing/managers.py index 0577908c425469..2bad636855fe62 100644 --- a/Lib/multiprocessing/managers.py +++ b/Lib/multiprocessing/managers.py @@ -598,10 +598,7 @@ def _run_server(cls, registry, address, authkey, serializer, writer, Create a server, report its address and run it ''' # bpo-36368: protect server process from KeyboardInterrupt signals - if sys.platform != 'win32': - signal.signal(signal.SIGINT, signal.SIG_IGN) - else: - signal.signal(signal.CTRL_C_EVENT, signal.SIG_IGN) + signal.signal(signal.SIGINT, signal.SIG_IGN) if initializer is not None: initializer(*initargs) diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py index f7709c77096486..50a581accf9519 100644 --- a/Lib/test/_test_multiprocessing.py +++ b/Lib/test/_test_multiprocessing.py @@ -3734,6 +3734,7 @@ def test_shared_memory_across_processes(self): sms.close() + @unittest.skipIf(WIN32, "test not feasible in Windows") def test_shared_memory_SharedMemoryServer_ignores_sigint(self): # bpo-36368: protect SharedMemoryManager server process from # KeyboardInterrupt signals. @@ -3745,10 +3746,7 @@ def test_shared_memory_SharedMemoryServer_ignores_sigint(self): # the manager's server should ignore KeyboardInterrupt signals, and # maintain its connection with the current process - if sys.platform != 'win32': - os.kill(smm._process.pid, signal.SIGINT) - else: - os.kill(smm._process.pid, signal.CTRL_C_EVENT) + os.kill(smm._process.pid, signal.SIGINT) sl2 = smm.ShareableList(range(10)) smm.shutdown() From 1316b8b1a70caca7bc1037dd7b1cf7681dc2151a Mon Sep 17 00:00:00 2001 From: Pierre Glaser Date: Wed, 27 Mar 2019 11:38:32 +0100 Subject: [PATCH 08/11] TST widen skip condition to non-posix platforms --- Lib/test/_test_multiprocessing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py index 50a581accf9519..a42794ff74dbb6 100644 --- a/Lib/test/_test_multiprocessing.py +++ b/Lib/test/_test_multiprocessing.py @@ -3734,7 +3734,7 @@ def test_shared_memory_across_processes(self): sms.close() - @unittest.skipIf(WIN32, "test not feasible in Windows") + @unittest.skipIf(os.name != "posix", "not feasible in non-posix platforms") def test_shared_memory_SharedMemoryServer_ignores_sigint(self): # bpo-36368: protect SharedMemoryManager server process from # KeyboardInterrupt signals. From 37efd996b345c67e2bf5bed3583eb2bc203939b7 Mon Sep 17 00:00:00 2001 From: Pierre Glaser Date: Wed, 27 Mar 2019 11:40:34 +0100 Subject: [PATCH 09/11] TST test that signal changes dont affect parent --- Lib/test/_test_multiprocessing.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py index a42794ff74dbb6..ec9823e71e8994 100644 --- a/Lib/test/_test_multiprocessing.py +++ b/Lib/test/_test_multiprocessing.py @@ -3745,10 +3745,17 @@ def test_shared_memory_SharedMemoryServer_ignores_sigint(self): sl = smm.ShareableList(range(10)) # the manager's server should ignore KeyboardInterrupt signals, and - # maintain its connection with the current process + # maintain its connection with the current process, and success when + # asked to deliver memory segments. os.kill(smm._process.pid, signal.SIGINT) sl2 = smm.ShareableList(range(10)) + + # test that the custom signal handler registered in the Manager do not + # affect signal handling in the parent process. + with self.assertRaises(KeyboardInterrupt): + os.kill(os.getpid(), signal.SIGINT) + smm.shutdown() def test_shared_memory_SharedMemoryManager_basics(self): From 74f943899a8f15c5b782a1080bfe1298b8e620c8 Mon Sep 17 00:00:00 2001 From: Pierre Glaser Date: Wed, 27 Mar 2019 11:54:57 +0100 Subject: [PATCH 10/11] CLN typo --- Lib/test/_test_multiprocessing.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py index ec9823e71e8994..a2569558ee3003 100644 --- a/Lib/test/_test_multiprocessing.py +++ b/Lib/test/_test_multiprocessing.py @@ -3751,8 +3751,8 @@ def test_shared_memory_SharedMemoryServer_ignores_sigint(self): sl2 = smm.ShareableList(range(10)) - # test that the custom signal handler registered in the Manager do not - # affect signal handling in the parent process. + # test that the custom signal handler registered in the Manager does + # not affect signal handling in the parent process. with self.assertRaises(KeyboardInterrupt): os.kill(os.getpid(), signal.SIGINT) From 01a1c0f016993461752b21d145e581382494797b Mon Sep 17 00:00:00 2001 From: Pierre Glaser Date: Wed, 27 Mar 2019 12:05:55 +0100 Subject: [PATCH 11/11] CLN bad indentation --- Lib/test/_test_multiprocessing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py index a2569558ee3003..d97e4232f7ac2e 100644 --- a/Lib/test/_test_multiprocessing.py +++ b/Lib/test/_test_multiprocessing.py @@ -3754,7 +3754,7 @@ def test_shared_memory_SharedMemoryServer_ignores_sigint(self): # test that the custom signal handler registered in the Manager does # not affect signal handling in the parent process. with self.assertRaises(KeyboardInterrupt): - os.kill(os.getpid(), signal.SIGINT) + os.kill(os.getpid(), signal.SIGINT) smm.shutdown()