bpo-30557: faulthandler now correctly filters and displays exception codes on Windows (#1924)

* bpo-30557: faulthandler now correctly filters and displays exception codes on Windows

* Adds test for non-fatal exceptions.

* Adds bpo number to comment.
This commit is contained in:
Steve Dower 2017-06-05 15:54:15 -07:00 committed by GitHub
parent 1bced56567
commit e6a23c8f9a
3 changed files with 33 additions and 4 deletions

View File

@ -754,6 +754,32 @@ class FaultHandlerTests(unittest.TestCase):
3, 3,
name) name)
@unittest.skipUnless(MS_WINDOWS, 'specific to Windows')
def test_raise_nonfatal_exception(self):
# These exceptions are not strictly errors. Letting
# faulthandler display the traceback when they are
# raised is likely to result in noise. However, they
# may still terminate the process if there is no
# handler installed for them (which there typically
# is, e.g. for debug messages).
for exc in (
0x00000000,
0x34567890,
0x40000000,
0x40001000,
0x70000000,
0x7FFFFFFF,
):
output, exitcode = self.get_output(f"""
import faulthandler
faulthandler.enable()
faulthandler._raise_exception(0x{exc:x})
"""
)
self.assertEqual(output, [])
# Actual exception code has bit 4 cleared
self.assertEqual(exitcode, exc & ~0x10000000)
@unittest.skipUnless(MS_WINDOWS, 'specific to Windows') @unittest.skipUnless(MS_WINDOWS, 'specific to Windows')
def test_disable_windows_exc_handler(self): def test_disable_windows_exc_handler(self):
code = dedent(""" code = dedent("""

View File

@ -345,6 +345,9 @@ Extension Modules
Library Library
------- -------
- bpo-30557: faulthandler now correctly filters and displays exception codes
on Windows
- bpo-30526: Add TextIOWrapper.reconfigure() and a TextIOWrapper.write_through - bpo-30526: Add TextIOWrapper.reconfigure() and a TextIOWrapper.write_through
attribute. attribute.

View File

@ -373,8 +373,8 @@ faulthandler_exc_handler(struct _EXCEPTION_POINTERS *exc_info)
DWORD code = exc_info->ExceptionRecord->ExceptionCode; DWORD code = exc_info->ExceptionRecord->ExceptionCode;
DWORD flags = exc_info->ExceptionRecord->ExceptionFlags; DWORD flags = exc_info->ExceptionRecord->ExceptionFlags;
/* only log fatal exceptions */ /* bpo-30557: only log fatal exceptions */
if (flags & EXCEPTION_NONCONTINUABLE) { if (!(code & 0x80000000)) {
/* call the next exception handler */ /* call the next exception handler */
return EXCEPTION_CONTINUE_SEARCH; return EXCEPTION_CONTINUE_SEARCH;
} }
@ -391,8 +391,8 @@ faulthandler_exc_handler(struct _EXCEPTION_POINTERS *exc_info)
case EXCEPTION_IN_PAGE_ERROR: PUTS(fd, "page error"); break; case EXCEPTION_IN_PAGE_ERROR: PUTS(fd, "page error"); break;
case EXCEPTION_STACK_OVERFLOW: PUTS(fd, "stack overflow"); break; case EXCEPTION_STACK_OVERFLOW: PUTS(fd, "stack overflow"); break;
default: default:
PUTS(fd, "code "); PUTS(fd, "code 0x");
_Py_DumpDecimal(fd, code); _Py_DumpHexadecimal(fd, code, 8);
} }
PUTS(fd, "\n\n"); PUTS(fd, "\n\n");