File bpo23395-PyErr_SetInterrupt-signal.patch of Package python3-base
161
1
From d823eee619c0e7c1a9bc5b0caa0d0fa4734ac052 Mon Sep 17 00:00:00 2001
2
From: =?UTF-8?q?Mat=C4=9Bj=20Cepl?= <mcepl@cepl.eu>
3
Date: Thu, 23 May 2019 22:30:00 +0200
4
Subject: [PATCH] bpo-23395: Fix PyErr_SetInterrupt if the SIGINT signal is
5
ignored or not handled (GH-7778)
6
MIME-Version: 1.0
7
Content-Type: text/plain; charset=UTF-8
8
Content-Transfer-Encoding: 8bit
9
10
``_thread.interrupt_main()`` now avoids setting the Python error status if the ``SIGINT`` signal is ignored or not handled by Python.
11
(cherry picked from commit 608876b6b1eb59538e6c29671a733033fb8b5be7)
12
13
Co-authored-by: Matěj Cepl <mcepl@cepl.eu>
14
---
15
Doc/c-api/exceptions.rst | 12 +++----
16
Doc/library/_thread.rst | 8 +++--
17
Lib/test/test_threading.py | 35 +++++++++++++++++++
18
Misc/ACKS | 2 +-
19
.../2016-07-27-11-06-43.bpo-23395.MuCEX9.rst | 2 ++
20
Modules/signalmodule.c | 13 ++++---
21
6 files changed, 59 insertions(+), 13 deletions(-)
22
create mode 100644 Misc/NEWS.d/next/Library/2016-07-27-11-06-43.bpo-23395.MuCEX9.rst
23
24
--- a/Doc/c-api/exceptions.rst
25
+++ b/Doc/c-api/exceptions.rst
26
27
single: SIGINT
28
single: KeyboardInterrupt (built-in exception)
29
30
- This function simulates the effect of a :const:`SIGINT` signal arriving --- the
31
- next time :c:func:`PyErr_CheckSignals` is called, :exc:`KeyboardInterrupt` will
32
- be raised. It may be called without holding the interpreter lock.
33
-
34
- .. % XXX This was described as obsolete, but is used in
35
- .. % _thread.interrupt_main() (used from IDLE), so it's still needed.
36
+ Simulate the effect of a :const:`SIGINT` signal arriving. The next time
37
+ :c:func:`PyErr_CheckSignals` is called, the Python signal handler for
38
+ :const:`SIGINT` will be called.
39
40
+ If :const:`SIGINT` isn't handled by Python (it was set to
41
+ :data:`signal.SIG_DFL` or :data:`signal.SIG_IGN`), this function does
42
+ nothing.
43
44
.. c:function:: int PySignal_SetWakeupFd(int fd)
45
46
--- a/Doc/library/_thread.rst
47
+++ b/Doc/library/_thread.rst
48
49
50
.. function:: interrupt_main()
51
52
- Raise a :exc:`KeyboardInterrupt` exception in the main thread. A subthread can
53
- use this function to interrupt the main thread.
54
+ Simulate the effect of a :data:`signal.SIGINT` signal arriving in the main
55
+ thread. A thread can use this function to interrupt the main thread.
56
+
57
+ If :data:`signal.SIGINT` isn't handled by Python (it was set to
58
+ :data:`signal.SIG_DFL` or :data:`signal.SIG_IGN`), this function does
59
+ nothing.
60
61
62
.. function:: exit()
63
--- a/Lib/test/test_threading.py
64
+++ b/Lib/test/test_threading.py
65
66
import weakref
67
import os
68
import subprocess
69
+import signal
70
71
from test import lock_tests
72
from test import support
73
74
class BarrierTests(lock_tests.BarrierTests):
75
barriertype = staticmethod(threading.Barrier)
76
77
+
78
class MiscTestCase(unittest.TestCase):
79
def test__all__(self):
80
extra = {"ThreadError"}
81
82
support.check__all__(self, threading, ('threading', '_thread'),
83
extra=extra, blacklist=blacklist)
84
85
+
86
+class InterruptMainTests(unittest.TestCase):
87
+ def test_interrupt_main_subthread(self):
88
+ # Calling start_new_thread with a function that executes interrupt_main
89
+ # should raise KeyboardInterrupt upon completion.
90
+ def call_interrupt():
91
+ _thread.interrupt_main()
92
+ t = threading.Thread(target=call_interrupt)
93
+ with self.assertRaises(KeyboardInterrupt):
94
+ t.start()
95
+ t.join()
96
+ t.join()
97
+
98
+ def test_interrupt_main_mainthread(self):
99
+ # Make sure that if interrupt_main is called in main thread that
100
+ # KeyboardInterrupt is raised instantly.
101
+ with self.assertRaises(KeyboardInterrupt):
102
+ _thread.interrupt_main()
103
+
104
+ def test_interrupt_main_noerror(self):
105
+ handler = signal.getsignal(signal.SIGINT)
106
+ try:
107
+ # No exception should arise.
108
+ signal.signal(signal.SIGINT, signal.SIG_IGN)
109
+ _thread.interrupt_main()
110
+
111
+ signal.signal(signal.SIGINT, signal.SIG_DFL)
112
+ _thread.interrupt_main()
113
+ finally:
114
+ # Restore original handler
115
+ signal.signal(signal.SIGINT, handler)
116
+
117
+
118
if __name__ == "__main__":
119
unittest.main()
120
--- a/Misc/ACKS
121
+++ b/Misc/ACKS
122
123
Charles Cazabon
124
Jesús Cea Avión
125
Per Cederqvist
126
-Matej Cepl
127
+Matěj Cepl
128
Carl Cerecke
129
Octavian Cerna
130
Michael Cetrulo
131
--- /dev/null
132
+++ b/Misc/NEWS.d/next/Library/2016-07-27-11-06-43.bpo-23395.MuCEX9.rst
133
134
+``_thread.interrupt_main()`` now avoids setting the Python error status
135
+if the ``SIGINT`` signal is ignored or not handled by Python.
136
--- a/Modules/signalmodule.c
137
+++ b/Modules/signalmodule.c
138
139
}
140
141
142
-/* Replacements for intrcheck.c functionality
143
- * Declared in pyerrors.h
144
- */
145
+/* Simulate the effect of a signal.SIGINT signal arriving. The next time
146
+ PyErr_CheckSignals is called, the Python SIGINT signal handler will be
147
+ raised.
148
+
149
+ Missing signal handler for the SIGINT signal is silently ignored. */
150
void
151
PyErr_SetInterrupt(void)
152
{
153
- trip_signal(SIGINT);
154
+ if ((Handlers[SIGINT].func != IgnoreHandler) &&
155
+ (Handlers[SIGINT].func != DefaultHandler)) {
156
+ trip_signal(SIGINT);
157
+ }
158
}
159
160
void
161