diff --git a/Lib/test/test_faulthandler.py b/Lib/test/test_faulthandler.py index 20fe1e26559..b8d8ea3cd47 100644 --- a/Lib/test/test_faulthandler.py +++ b/Lib/test/test_faulthandler.py @@ -755,6 +755,22 @@ class FaultHandlerTests(unittest.TestCase): 3, name) + @unittest.skipUnless(MS_WINDOWS, 'specific to Windows') + def test_ignore_exception(self): + for exc_code in ( + 0xE06D7363, # MSC exception ("Emsc") + 0xE0434352, # COM Callable Runtime exception ("ECCR") + ): + code = f""" + import faulthandler + faulthandler.enable() + faulthandler._raise_exception({exc_code}) + """ + code = dedent(code) + output, exitcode = self.get_output(code) + self.assertEqual(output, []) + self.assertEqual(exitcode, exc_code) + @unittest.skipUnless(MS_WINDOWS, 'specific to Windows') def test_raise_nonfatal_exception(self): # These exceptions are not strictly errors. Letting diff --git a/Misc/NEWS.d/next/Library/2017-10-09-17-42-30.bpo-31701.NRrVel.rst b/Misc/NEWS.d/next/Library/2017-10-09-17-42-30.bpo-31701.NRrVel.rst new file mode 100644 index 00000000000..129b74e5ce2 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-10-09-17-42-30.bpo-31701.NRrVel.rst @@ -0,0 +1 @@ +On Windows, faulthandler.enable() now ignores MSC and COM exceptions. diff --git a/Modules/faulthandler.c b/Modules/faulthandler.c index 2efa998ff89..d5194cad610 100644 --- a/Modules/faulthandler.c +++ b/Modules/faulthandler.c @@ -366,6 +366,23 @@ faulthandler_fatal_error(int signum) } #ifdef MS_WINDOWS +static int +faulthandler_ignore_exception(DWORD code) +{ + /* bpo-30557: ignore exceptions which are not errors */ + if (!(code & 0x80000000)) { + return 1; + } + /* bpo-31701: ignore MSC and COM exceptions + E0000000 + code */ + if (code == 0xE06D7363 /* MSC exception ("Emsc") */ + || code == 0xE0434352 /* COM Callable Runtime exception ("ECCR") */) { + return 1; + } + /* Interesting exception: log it with the Python traceback */ + return 0; +} + static LONG WINAPI faulthandler_exc_handler(struct _EXCEPTION_POINTERS *exc_info) { @@ -373,9 +390,8 @@ faulthandler_exc_handler(struct _EXCEPTION_POINTERS *exc_info) DWORD code = exc_info->ExceptionRecord->ExceptionCode; DWORD flags = exc_info->ExceptionRecord->ExceptionFlags; - /* bpo-30557: only log fatal exceptions */ - if (!(code & 0x80000000)) { - /* call the next exception handler */ + if (faulthandler_ignore_exception(code)) { + /* ignore the exception: call the next exception handler */ return EXCEPTION_CONTINUE_SEARCH; }