[Python-checkins] bpo-42923: Add Py_FatalError() test in test_capi (GH-24240)

vstinner webhook-mailer at python.org
Mon Jan 18 12:24:53 EST 2021


https://github.com/python/cpython/commit/e232025025c8bd07c1d1b12a583a80c4a673f077
commit: e232025025c8bd07c1d1b12a583a80c4a673f077
branch: master
author: Victor Stinner <vstinner at python.org>
committer: vstinner <vstinner at python.org>
date: 2021-01-18T18:24:29+01:00
summary:

bpo-42923: Add Py_FatalError() test in test_capi (GH-24240)

Move faulthandler._fatal_error() to _testcapi.fatal_error().

files:
M Lib/test/test_capi.py
M Lib/test/test_faulthandler.py
M Modules/_testcapimodule.c
M Modules/faulthandler.c

diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py
index a4ebe4a0a1b5c..0d5c97dcc2a4a 100644
--- a/Lib/test/test_capi.py
+++ b/Lib/test/test_capi.py
@@ -547,6 +547,15 @@ def test_pynumber_tobase(self):
         self.assertRaises(TypeError, pynumber_tobase, '123', 10)
         self.assertRaises(SystemError, pynumber_tobase, 123, 0)
 
+    def test_fatal_error(self):
+        code = 'import _testcapi; _testcapi.fatal_error(b"MESSAGE")'
+        with support.SuppressCrashReport():
+            rc, out, err = assert_python_failure('-sSI', '-c', code)
+
+        err = err.replace(b'\r', b'').decode('ascii', 'replace')
+        self.assertIn('Fatal Python error: test_fatal_error: MESSAGE\n',
+                      err)
+
 
 class TestPendingCalls(unittest.TestCase):
 
diff --git a/Lib/test/test_faulthandler.py b/Lib/test/test_faulthandler.py
index 80c1f7d90adf0..bc61aab9c0fc2 100644
--- a/Lib/test/test_faulthandler.py
+++ b/Lib/test/test_faulthandler.py
@@ -227,25 +227,23 @@ def test_sigill(self):
             5,
             'Illegal instruction')
 
+    def check_fatal_error_func(self, release_gil):
+        # Test that Py_FatalError() dumps a traceback
+        with support.SuppressCrashReport():
+            self.check_fatal_error(f"""
+                import _testcapi
+                _testcapi.fatal_error(b'xyz', {release_gil})
+                """,
+                2,
+                'xyz',
+                func='test_fatal_error',
+                py_fatal_error=True)
+
     def test_fatal_error(self):
-        self.check_fatal_error("""
-            import faulthandler
-            faulthandler._fatal_error(b'xyz')
-            """,
-            2,
-            'xyz',
-            func='faulthandler_fatal_error_py',
-            py_fatal_error=True)
+        self.check_fatal_error_func(False)
 
     def test_fatal_error_without_gil(self):
-        self.check_fatal_error("""
-            import faulthandler
-            faulthandler._fatal_error(b'xyz', True)
-            """,
-            2,
-            'xyz',
-            func='faulthandler_fatal_error_py',
-            py_fatal_error=True)
+        self.check_fatal_error_func(True)
 
     @unittest.skipIf(sys.platform.startswith('openbsd'),
                      "Issue #12868: sigaltstack() doesn't work on "
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c
index 4f97927fa2322..2a5b3d9c50b62 100644
--- a/Modules/_testcapimodule.c
+++ b/Modules/_testcapimodule.c
@@ -5665,6 +5665,27 @@ test_refcount(PyObject *self, PyObject *Py_UNUSED(ignored))
 }
 
 
+static PyObject *
+test_fatal_error(PyObject *self, PyObject *args)
+{
+    char *message;
+    int release_gil = 0;
+    if (!PyArg_ParseTuple(args, "y|i:fatal_error", &message, &release_gil))
+        return NULL;
+    if (release_gil) {
+        Py_BEGIN_ALLOW_THREADS
+        Py_FatalError(message);
+        Py_END_ALLOW_THREADS
+    }
+    else {
+        Py_FatalError(message);
+    }
+    // Py_FatalError() does not return, but exits the process.
+    Py_RETURN_NONE;
+}
+
+
+
 static PyMethodDef TestMethods[] = {
     {"raise_exception",         raise_exception,                 METH_VARARGS},
     {"raise_memoryerror",       raise_memoryerror,               METH_NOARGS},
@@ -5938,6 +5959,8 @@ static PyMethodDef TestMethods[] = {
     {"without_gc", without_gc, METH_O},
     {"test_set_type_size", test_set_type_size, METH_NOARGS},
     {"test_refcount", test_refcount, METH_NOARGS},
+    {"fatal_error", test_fatal_error, METH_VARARGS,
+     PyDoc_STR("fatal_error(message, release_gil=False): call Py_FatalError(message)")},
     {NULL, NULL} /* sentinel */
 };
 
diff --git a/Modules/faulthandler.c b/Modules/faulthandler.c
index 67fe1ca9ffffd..fe5dbc1cc0fee 100644
--- a/Modules/faulthandler.c
+++ b/Modules/faulthandler.c
@@ -1,6 +1,6 @@
 #include "Python.h"
-#include "pycore_initconfig.h"
-#include "pycore_traceback.h"
+#include "pycore_initconfig.h"    // _PyStatus_ERR
+#include "pycore_traceback.h"     // _Py_DumpTracebackThreads
 #include <signal.h>
 #include <object.h>
 #include <frameobject.h>
@@ -1123,25 +1123,6 @@ faulthandler_sigabrt(PyObject *self, PyObject *args)
     Py_RETURN_NONE;
 }
 
-static PyObject *
-faulthandler_fatal_error_py(PyObject *self, PyObject *args)
-{
-    char *message;
-    int release_gil = 0;
-    if (!PyArg_ParseTuple(args, "y|i:fatal_error", &message, &release_gil))
-        return NULL;
-    faulthandler_suppress_crash_report();
-    if (release_gil) {
-        Py_BEGIN_ALLOW_THREADS
-        Py_FatalError(message);
-        Py_END_ALLOW_THREADS
-    }
-    else {
-        Py_FatalError(message);
-    }
-    Py_RETURN_NONE;
-}
-
 #if defined(FAULTHANDLER_USE_ALT_STACK)
 #define FAULTHANDLER_STACK_OVERFLOW
 
@@ -1278,8 +1259,6 @@ static PyMethodDef module_methods[] = {
      PyDoc_STR("_sigabrt(): raise a SIGABRT signal")},
     {"_sigfpe", (PyCFunction)faulthandler_sigfpe, METH_NOARGS,
      PyDoc_STR("_sigfpe(): raise a SIGFPE signal")},
-    {"_fatal_error", faulthandler_fatal_error_py, METH_VARARGS,
-     PyDoc_STR("_fatal_error(message): call Py_FatalError(message)")},
 #ifdef FAULTHANDLER_STACK_OVERFLOW
     {"_stack_overflow", faulthandler_stack_overflow, METH_NOARGS,
      PyDoc_STR("_stack_overflow(): recursive call to raise a stack overflow")},



More information about the Python-checkins mailing list