Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 56e8c29

Browse files
committed
Issue #22018: Add _testcapi.raise_signal()
- Use _testcapi.raise_signal() in test_signal - close also os.pipe() file descriptors in some test_signal tests where they were not closed properly - Remove faulthandler._sigill() and faulthandler._sigbus(): reuse _testcapi.raise_signal() in test_faulthandler
1 parent 569a7fa commit 56e8c29

4 files changed

Lines changed: 85 additions & 53 deletions

File tree

Lib/test/test_faulthandler.py

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616
HAVE_THREADS = True
1717
except ImportError:
1818
HAVE_THREADS = False
19+
try:
20+
import _testcapi
21+
except ImportError:
22+
_testcapi = None
1923

2024
TIMEOUT = 0.5
2125

@@ -133,26 +137,32 @@ def test_sigfpe(self):
133137
3,
134138
'Floating point exception')
135139

136-
@unittest.skipIf(not hasattr(faulthandler, '_sigbus'),
137-
"need faulthandler._sigbus()")
140+
@unittest.skipIf(_testcapi is None, 'need _testcapi')
141+
@unittest.skipUnless(hasattr(signal, 'SIGBUS'), 'need signal.SIGBUS')
138142
def test_sigbus(self):
139143
self.check_fatal_error("""
144+
import _testcapi
140145
import faulthandler
146+
import signal
147+
141148
faulthandler.enable()
142-
faulthandler._sigbus()
149+
_testcapi.raise_signal(signal.SIGBUS)
143150
""".strip(),
144-
3,
151+
6,
145152
'Bus error')
146153

147-
@unittest.skipIf(not hasattr(faulthandler, '_sigill'),
148-
"need faulthandler._sigill()")
154+
@unittest.skipIf(_testcapi is None, 'need _testcapi')
155+
@unittest.skipUnless(hasattr(signal, 'SIGILL'), 'need signal.SIGILL')
149156
def test_sigill(self):
150157
self.check_fatal_error("""
158+
import _testcapi
151159
import faulthandler
160+
import signal
161+
152162
faulthandler.enable()
153-
faulthandler._sigill()
163+
_testcapi.raise_signal(signal.SIGILL)
154164
""".strip(),
155-
3,
165+
6,
156166
'Illegal instruction')
157167

158168
def test_fatal_error(self):

Lib/test/test_signal.py

Lines changed: 46 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@
1515
import threading
1616
except ImportError:
1717
threading = None
18+
try:
19+
import _testcapi
20+
except ImportError:
21+
_testcapi = None
1822

1923

2024
class HandlerBCalled(Exception):
@@ -250,12 +254,27 @@ def test_invalid_fd(self):
250254
fd = support.make_bad_fd()
251255
self.assertRaises(ValueError, signal.set_wakeup_fd, fd)
252256

257+
def test_set_wakeup_fd_result(self):
258+
r1, w1 = os.pipe()
259+
os.close(r1)
260+
self.addCleanup(os.close, w1)
261+
r2, w2 = os.pipe()
262+
os.close(r2)
263+
self.addCleanup(os.close, w2)
264+
265+
signal.set_wakeup_fd(w1)
266+
self.assertIs(signal.set_wakeup_fd(w2), w1)
267+
self.assertIs(signal.set_wakeup_fd(-1), w2)
268+
self.assertIs(signal.set_wakeup_fd(-1), -1)
269+
253270

254271
@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
255272
class WakeupSignalTests(unittest.TestCase):
273+
@unittest.skipIf(_testcapi is None, 'need _testcapi')
256274
def check_wakeup(self, test_body, *signals, ordered=True):
257275
# use a subprocess to have only one thread
258276
code = """if 1:
277+
import _testcapi
259278
import fcntl
260279
import os
261280
import signal
@@ -294,17 +313,18 @@ def check_signum(signals):
294313

295314
assert_python_ok('-c', code)
296315

316+
@unittest.skipIf(_testcapi is None, 'need _testcapi')
297317
def test_wakeup_write_error(self):
298318
# Issue #16105: write() errors in the C signal handler should not
299319
# pass silently.
300320
# Use a subprocess to have only one thread.
301321
code = """if 1:
322+
import _testcapi
302323
import errno
303324
import fcntl
304325
import os
305326
import signal
306327
import sys
307-
import time
308328
from test.support import captured_stderr
309329
310330
def handler(signum, frame):
@@ -319,8 +339,7 @@ def handler(signum, frame):
319339
signal.set_wakeup_fd(r)
320340
try:
321341
with captured_stderr() as err:
322-
signal.alarm(1)
323-
time.sleep(5.0)
342+
_testcapi.raise_signal(signal.SIGALRM)
324343
except ZeroDivisionError:
325344
# An ignored exception should have been printed out on stderr
326345
err = err.getvalue()
@@ -331,6 +350,9 @@ def handler(signum, frame):
331350
raise AssertionError(err)
332351
else:
333352
raise AssertionError("ZeroDivisionError not raised")
353+
354+
os.close(r)
355+
os.close(w)
334356
"""
335357
r, w = os.pipe()
336358
try:
@@ -394,9 +416,10 @@ def test_wakeup_fd_during(self):
394416

395417
def test_signum(self):
396418
self.check_wakeup("""def test():
419+
import _testcapi
397420
signal.signal(signal.SIGUSR1, handler)
398-
os.kill(os.getpid(), signal.SIGUSR1)
399-
os.kill(os.getpid(), signal.SIGALRM)
421+
_testcapi.raise_signal(signal.SIGUSR1)
422+
_testcapi.raise_signal(signal.SIGALRM)
400423
""", signal.SIGUSR1, signal.SIGALRM)
401424

402425
@unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
@@ -410,8 +433,8 @@ def test_pending(self):
410433
signal.signal(signum2, handler)
411434
412435
signal.pthread_sigmask(signal.SIG_BLOCK, (signum1, signum2))
413-
os.kill(os.getpid(), signum1)
414-
os.kill(os.getpid(), signum2)
436+
_testcapi.raise_signal(signum1)
437+
_testcapi.raise_signal(signum2)
415438
# Unblocking the 2 signals calls the C signal handler twice
416439
signal.pthread_sigmask(signal.SIG_UNBLOCK, (signum1, signum2))
417440
""", signal.SIGUSR1, signal.SIGUSR2, ordered=False)
@@ -447,18 +470,22 @@ def handler(signum, frame):
447470
sys.stdout.flush()
448471
449472
# run the test twice
450-
for loop in range(2):
451-
# send a SIGALRM in a second (during the read)
452-
signal.alarm(1)
453-
try:
454-
# blocking call: read from a pipe without data
455-
os.read(r, 1)
456-
except OSError as err:
457-
if err.errno != errno.EINTR:
458-
raise
459-
else:
460-
sys.exit(2)
461-
sys.exit(3)
473+
try:
474+
for loop in range(2):
475+
# send a SIGALRM in a second (during the read)
476+
signal.alarm(1)
477+
try:
478+
# blocking call: read from a pipe without data
479+
os.read(r, 1)
480+
except OSError as err:
481+
if err.errno != errno.EINTR:
482+
raise
483+
else:
484+
sys.exit(2)
485+
sys.exit(3)
486+
finally:
487+
os.close(r)
488+
os.close(w)
462489
""" % (interrupt,)
463490
with spawn_python('-c', code) as process:
464491
try:

Modules/_testcapimodule.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <float.h>
1212
#include "structmember.h"
1313
#include "datetime.h"
14+
#include <signal.h>
1415

1516
#ifdef WITH_THREAD
1617
#include "pythread.h"
@@ -3063,6 +3064,24 @@ call_in_temporary_c_thread(PyObject *self, PyObject *callback)
30633064
}
30643065
#endif /* WITH_THREAD */
30653066

3067+
static PyObject*
3068+
test_raise_signal(PyObject* self, PyObject *args)
3069+
{
3070+
int signum, err;
3071+
3072+
if (PyArg_ParseTuple(args, "i:raise_signal", &signum) < 0)
3073+
return NULL;
3074+
3075+
err = raise(signum);
3076+
if (err)
3077+
return PyErr_SetFromErrno(PyExc_OSError);
3078+
3079+
if (PyErr_CheckSignals() < 0)
3080+
return NULL;
3081+
3082+
Py_RETURN_NONE;
3083+
}
3084+
30663085

30673086
static PyMethodDef TestMethods[] = {
30683087
{"raise_exception", raise_exception, METH_VARARGS},
@@ -3198,6 +3217,8 @@ static PyMethodDef TestMethods[] = {
31983217
{"docstring_with_signature_with_defaults",
31993218
(PyCFunction)test_with_docstring, METH_NOARGS,
32003219
docstring_with_signature_with_defaults},
3220+
{"raise_signal",
3221+
(PyCFunction)test_raise_signal, METH_VARARGS},
32013222
#ifdef WITH_THREAD
32023223
{"call_in_temporary_c_thread", call_in_temporary_c_thread, METH_O,
32033224
PyDoc_STR("set_error_class(error_class) -> None")},

Modules/faulthandler.c

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -874,24 +874,6 @@ faulthandler_sigabrt(PyObject *self, PyObject *args)
874874
Py_RETURN_NONE;
875875
}
876876

877-
#ifdef SIGBUS
878-
static PyObject *
879-
faulthandler_sigbus(PyObject *self, PyObject *args)
880-
{
881-
raise(SIGBUS);
882-
Py_RETURN_NONE;
883-
}
884-
#endif
885-
886-
#ifdef SIGILL
887-
static PyObject *
888-
faulthandler_sigill(PyObject *self, PyObject *args)
889-
{
890-
raise(SIGILL);
891-
Py_RETURN_NONE;
892-
}
893-
#endif
894-
895877
static PyObject *
896878
faulthandler_fatal_error_py(PyObject *self, PyObject *args)
897879
{
@@ -1012,14 +994,6 @@ static PyMethodDef module_methods[] = {
1012994
PyDoc_STR("_sigabrt(): raise a SIGABRT signal")},
1013995
{"_sigfpe", (PyCFunction)faulthandler_sigfpe, METH_NOARGS,
1014996
PyDoc_STR("_sigfpe(): raise a SIGFPE signal")},
1015-
#ifdef SIGBUS
1016-
{"_sigbus", (PyCFunction)faulthandler_sigbus, METH_NOARGS,
1017-
PyDoc_STR("_sigbus(): raise a SIGBUS signal")},
1018-
#endif
1019-
#ifdef SIGILL
1020-
{"_sigill", (PyCFunction)faulthandler_sigill, METH_NOARGS,
1021-
PyDoc_STR("_sigill(): raise a SIGILL signal")},
1022-
#endif
1023997
{"_fatal_error", faulthandler_fatal_error_py, METH_VARARGS,
1024998
PyDoc_STR("_fatal_error(message): call Py_FatalError(message)")},
1025999
#if defined(HAVE_SIGALTSTACK) && defined(HAVE_SIGACTION)

0 commit comments

Comments
 (0)