Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 46c2b81

Browse filesBrowse files
authored
bpo-30125: Fix faulthandler.disable() on Windows (#1240)
* bpo-30125: Cleanup faulthandler.c * Use size_t type for iterators * Add { ... } * bpo-30125: Fix faulthandler.disable() on Windows On Windows, faulthandler.disable() now removes the exception handler installed by faulthandler.enable().
1 parent 2a1aed0 commit 46c2b81
Copy full SHA for 46c2b81

File tree

2 files changed

+31
-24
lines changed
Filter options

2 files changed

+31
-24
lines changed

‎Lib/test/test_faulthandler.py

Copy file name to clipboardExpand all lines: Lib/test/test_faulthandler.py
+12Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -754,6 +754,18 @@ def test_raise_exception(self):
754754
3,
755755
name)
756756

757+
@unittest.skipUnless(MS_WINDOWS, 'specific to Windows')
758+
def test_disable_windows_exc_handler(self):
759+
code = dedent("""
760+
import faulthandler
761+
faulthandler.enable()
762+
faulthandler.disable()
763+
code = faulthandler._EXCEPTION_ACCESS_VIOLATION
764+
faulthandler._raise_exception(code)
765+
""")
766+
output, exitcode = self.get_output(code)
767+
self.assertEqual(output, [])
768+
self.assertEqual(exitcode, 0xC0000005)
757769

758770

759771
if __name__ == "__main__":

‎Modules/faulthandler.c

Copy file name to clipboardExpand all lines: Modules/faulthandler.c
+19-24Lines changed: 19 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ static struct {
5555
int fd;
5656
int all_threads;
5757
PyInterpreterState *interp;
58+
#ifdef MS_WINDOWS
59+
void *exc_handler;
60+
#endif
5861
} fatal_error = {0, NULL, -1, 0};
5962

6063
#ifdef FAULTHANDLER_LATER
@@ -395,8 +398,7 @@ faulthandler_exc_handler(struct _EXCEPTION_POINTERS *exc_info)
395398

396399
if (code == EXCEPTION_ACCESS_VIOLATION) {
397400
/* disable signal handler for SIGSEGV */
398-
size_t i;
399-
for (i=0; i < faulthandler_nsignals; i++) {
401+
for (size_t i=0; i < faulthandler_nsignals; i++) {
400402
fault_handler_t *handler = &faulthandler_handlers[i];
401403
if (handler->signum == SIGSEGV) {
402404
faulthandler_disable_fatal_handler(handler);
@@ -418,14 +420,12 @@ faulthandler_exc_handler(struct _EXCEPTION_POINTERS *exc_info)
418420
static int
419421
faulthandler_enable(void)
420422
{
421-
size_t i;
422-
423423
if (fatal_error.enabled) {
424424
return 0;
425425
}
426426
fatal_error.enabled = 1;
427427

428-
for (i=0; i < faulthandler_nsignals; i++) {
428+
for (size_t i=0; i < faulthandler_nsignals; i++) {
429429
fault_handler_t *handler;
430430
#ifdef HAVE_SIGACTION
431431
struct sigaction action;
@@ -462,7 +462,8 @@ faulthandler_enable(void)
462462
}
463463

464464
#ifdef MS_WINDOWS
465-
AddVectoredExceptionHandler(1, faulthandler_exc_handler);
465+
assert(fatal_error.exc_handler == NULL);
466+
fatal_error.exc_handler = AddVectoredExceptionHandler(1, faulthandler_exc_handler);
466467
#endif
467468
return 0;
468469
}
@@ -504,17 +505,20 @@ faulthandler_py_enable(PyObject *self, PyObject *args, PyObject *kwargs)
504505
static void
505506
faulthandler_disable(void)
506507
{
507-
unsigned int i;
508-
fault_handler_t *handler;
509-
510508
if (fatal_error.enabled) {
511509
fatal_error.enabled = 0;
512-
for (i=0; i < faulthandler_nsignals; i++) {
510+
for (size_t i=0; i < faulthandler_nsignals; i++) {
511+
fault_handler_t *handler;
513512
handler = &faulthandler_handlers[i];
514513
faulthandler_disable_fatal_handler(handler);
515514
}
516515
}
517-
516+
#ifdef MS_WINDOWS
517+
if (fatal_error.exc_handler != NULL) {
518+
RemoveVectoredExceptionHandler(fatal_error.exc_handler);
519+
fatal_error.exc_handler = NULL;
520+
}
521+
#endif
518522
Py_CLEAR(fatal_error.file);
519523
}
520524

@@ -777,9 +781,7 @@ faulthandler_user(int signum)
777781
static int
778782
check_signum(int signum)
779783
{
780-
unsigned int i;
781-
782-
for (i=0; i < faulthandler_nsignals; i++) {
784+
for (size_t i=0; i < faulthandler_nsignals; i++) {
783785
if (faulthandler_handlers[i].signum == signum) {
784786
PyErr_Format(PyExc_RuntimeError,
785787
"signal %i cannot be registered, "
@@ -1122,16 +1124,12 @@ faulthandler_stack_overflow(PyObject *self)
11221124
static int
11231125
faulthandler_traverse(PyObject *module, visitproc visit, void *arg)
11241126
{
1125-
#ifdef FAULTHANDLER_USER
1126-
unsigned int signum;
1127-
#endif
1128-
11291127
#ifdef FAULTHANDLER_LATER
11301128
Py_VISIT(thread.file);
11311129
#endif
11321130
#ifdef FAULTHANDLER_USER
11331131
if (user_signals != NULL) {
1134-
for (signum=0; signum < NSIG; signum++)
1132+
for (size_t signum=0; signum < NSIG; signum++)
11351133
Py_VISIT(user_signals[signum].file);
11361134
}
11371135
#endif
@@ -1342,10 +1340,6 @@ int _PyFaulthandler_Init(void)
13421340

13431341
void _PyFaulthandler_Fini(void)
13441342
{
1345-
#ifdef FAULTHANDLER_USER
1346-
unsigned int signum;
1347-
#endif
1348-
13491343
#ifdef FAULTHANDLER_LATER
13501344
/* later */
13511345
if (thread.cancel_event) {
@@ -1363,8 +1357,9 @@ void _PyFaulthandler_Fini(void)
13631357
#ifdef FAULTHANDLER_USER
13641358
/* user */
13651359
if (user_signals != NULL) {
1366-
for (signum=0; signum < NSIG; signum++)
1360+
for (size_t signum=0; signum < NSIG; signum++) {
13671361
faulthandler_unregister(&user_signals[signum], signum);
1362+
}
13681363
PyMem_Free(user_signals);
13691364
user_signals = NULL;
13701365
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.