[Python-checkins] bpo-23395: Fix PyErr_SetInterrupt if the SIGINT signal is ignored or not handled (GH-7778)

Miss Islington (bot) webhook-mailer at python.org
Fri May 24 05:22:43 EDT 2019


https://github.com/python/cpython/commit/310f414bbd4d6ed1d8813f724c91ce9b4129c0ba
commit: 310f414bbd4d6ed1d8813f724c91ce9b4129c0ba
branch: 3.7
author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com>
committer: GitHub <noreply at github.com>
date: 2019年05月24日T02:22:38-07:00
summary:
bpo-23395: Fix PyErr_SetInterrupt if the SIGINT signal is ignored or not handled (GH-7778)
``_thread.interrupt_main()`` now avoids setting the Python error status if the ``SIGINT`` signal is ignored or not handled by Python.
(cherry picked from commit 608876b6b1eb59538e6c29671a733033fb8b5be7)
Co-authored-by: Matěj Cepl <mcepl at cepl.eu>
files:
A Misc/NEWS.d/next/Library/2016-07-27-11-06-43.bpo-23395.MuCEX9.rst
M Doc/c-api/exceptions.rst
M Doc/library/_thread.rst
M Lib/test/test_threading.py
M Misc/ACKS
M Modules/signalmodule.c
diff --git a/Doc/c-api/exceptions.rst b/Doc/c-api/exceptions.rst
index 79e6f97a44c7..13e00b544818 100644
--- a/Doc/c-api/exceptions.rst
+++ b/Doc/c-api/exceptions.rst
@@ -516,13 +516,13 @@ Signal Handling
 single: SIGINT
 single: KeyboardInterrupt (built-in exception)
 
- This function simulates the effect of a :const:`SIGINT` signal arriving --- the
- next time :c:func:`PyErr_CheckSignals` is called, :exc:`KeyboardInterrupt` will
- be raised. It may be called without holding the interpreter lock.
-
- .. % XXX This was described as obsolete, but is used in
- .. % _thread.interrupt_main() (used from IDLE), so it's still needed.
+ Simulate the effect of a :const:`SIGINT` signal arriving. The next time
+ :c:func:`PyErr_CheckSignals` is called, the Python signal handler for
+ :const:`SIGINT` will be called.
 
+ If :const:`SIGINT` isn't handled by Python (it was set to
+ :data:`signal.SIG_DFL` or :data:`signal.SIG_IGN`), this function does
+ nothing.
 
 .. c:function:: int PySignal_SetWakeupFd(int fd)
 
diff --git a/Doc/library/_thread.rst b/Doc/library/_thread.rst
index acffabf24bad..d1c28f479e94 100644
--- a/Doc/library/_thread.rst
+++ b/Doc/library/_thread.rst
@@ -53,8 +53,12 @@ This module defines the following constants and functions:
 
 .. function:: interrupt_main()
 
- Raise a :exc:`KeyboardInterrupt` exception in the main thread. A subthread can
- use this function to interrupt the main thread.
+ Simulate the effect of a :data:`signal.SIGINT` signal arriving in the main
+ thread. A thread can use this function to interrupt the main thread.
+
+ If :data:`signal.SIGINT` isn't handled by Python (it was set to
+ :data:`signal.SIG_DFL` or :data:`signal.SIG_IGN`), this function does
+ nothing.
 
 
 .. function:: exit()
diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py
index 27f328dbe63c..aa810bda1c2a 100644
--- a/Lib/test/test_threading.py
+++ b/Lib/test/test_threading.py
@@ -16,6 +16,7 @@
 import weakref
 import os
 import subprocess
+import signal
 
 from test import lock_tests
 from test import support
@@ -1165,6 +1166,7 @@ class BoundedSemaphoreTests(lock_tests.BoundedSemaphoreTests):
 class BarrierTests(lock_tests.BarrierTests):
 barriertype = staticmethod(threading.Barrier)
 
+
 class MiscTestCase(unittest.TestCase):
 def test__all__(self):
 extra = {"ThreadError"}
@@ -1172,5 +1174,38 @@ def test__all__(self):
 support.check__all__(self, threading, ('threading', '_thread'),
 extra=extra, blacklist=blacklist)
 
+
+class InterruptMainTests(unittest.TestCase):
+ def test_interrupt_main_subthread(self):
+ # Calling start_new_thread with a function that executes interrupt_main
+ # should raise KeyboardInterrupt upon completion.
+ def call_interrupt():
+ _thread.interrupt_main()
+ t = threading.Thread(target=call_interrupt)
+ with self.assertRaises(KeyboardInterrupt):
+ t.start()
+ t.join()
+ t.join()
+
+ def test_interrupt_main_mainthread(self):
+ # Make sure that if interrupt_main is called in main thread that
+ # KeyboardInterrupt is raised instantly.
+ with self.assertRaises(KeyboardInterrupt):
+ _thread.interrupt_main()
+
+ def test_interrupt_main_noerror(self):
+ handler = signal.getsignal(signal.SIGINT)
+ try:
+ # No exception should arise.
+ signal.signal(signal.SIGINT, signal.SIG_IGN)
+ _thread.interrupt_main()
+
+ signal.signal(signal.SIGINT, signal.SIG_DFL)
+ _thread.interrupt_main()
+ finally:
+ # Restore original handler
+ signal.signal(signal.SIGINT, handler)
+
+
 if __name__ == "__main__":
 unittest.main()
diff --git a/Misc/ACKS b/Misc/ACKS
index 6664f711f63e..40e799088645 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -257,7 +257,7 @@ Donn Cave
 Charles Cazabon
 Jesús Cea Avión
 Per Cederqvist
-Matej Cepl
+Matěj Cepl
 Carl Cerecke
 Octavian Cerna
 Michael Cetrulo
diff --git a/Misc/NEWS.d/next/Library/2016-07-27-11-06-43.bpo-23395.MuCEX9.rst b/Misc/NEWS.d/next/Library/2016-07-27-11-06-43.bpo-23395.MuCEX9.rst
new file mode 100644
index 000000000000..ec95320ab411
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2016-07-27-11-06-43.bpo-23395.MuCEX9.rst
@@ -0,0 +1,2 @@
+``_thread.interrupt_main()`` now avoids setting the Python error status
+if the ``SIGINT`` signal is ignored or not handled by Python.
diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c
index e70c6fc3969a..a0722b731c87 100644
--- a/Modules/signalmodule.c
+++ b/Modules/signalmodule.c
@@ -1562,13 +1562,18 @@ PyErr_CheckSignals(void)
 }
 
 
-/* Replacements for intrcheck.c functionality
- * Declared in pyerrors.h
- */
+/* Simulate the effect of a signal.SIGINT signal arriving. The next time
+ PyErr_CheckSignals is called, the Python SIGINT signal handler will be
+ raised.
+
+ Missing signal handler for the SIGINT signal is silently ignored. */
 void
 PyErr_SetInterrupt(void)
 {
- trip_signal(SIGINT);
+ if ((Handlers[SIGINT].func != IgnoreHandler) &&
+ (Handlers[SIGINT].func != DefaultHandler)) {
+ trip_signal(SIGINT);
+ }
 }
 
 void


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /