mirror of
https://github.com/python/cpython.git
synced 2025-09-26 10:19:53 +00:00
bpo-42923: Add Py_FatalError() test in test_capi (GH-24240)
Move faulthandler._fatal_error() to _testcapi.fatal_error().
This commit is contained in:
parent
998ae1fa3f
commit
e232025025
4 changed files with 48 additions and 39 deletions
|
@ -547,6 +547,15 @@ class CAPITest(unittest.TestCase):
|
||||||
self.assertRaises(TypeError, pynumber_tobase, '123', 10)
|
self.assertRaises(TypeError, pynumber_tobase, '123', 10)
|
||||||
self.assertRaises(SystemError, pynumber_tobase, 123, 0)
|
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):
|
class TestPendingCalls(unittest.TestCase):
|
||||||
|
|
||||||
|
|
|
@ -227,25 +227,23 @@ class FaultHandlerTests(unittest.TestCase):
|
||||||
5,
|
5,
|
||||||
'Illegal instruction')
|
'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):
|
def test_fatal_error(self):
|
||||||
self.check_fatal_error("""
|
self.check_fatal_error_func(False)
|
||||||
import faulthandler
|
|
||||||
faulthandler._fatal_error(b'xyz')
|
|
||||||
""",
|
|
||||||
2,
|
|
||||||
'xyz',
|
|
||||||
func='faulthandler_fatal_error_py',
|
|
||||||
py_fatal_error=True)
|
|
||||||
|
|
||||||
def test_fatal_error_without_gil(self):
|
def test_fatal_error_without_gil(self):
|
||||||
self.check_fatal_error("""
|
self.check_fatal_error_func(True)
|
||||||
import faulthandler
|
|
||||||
faulthandler._fatal_error(b'xyz', True)
|
|
||||||
""",
|
|
||||||
2,
|
|
||||||
'xyz',
|
|
||||||
func='faulthandler_fatal_error_py',
|
|
||||||
py_fatal_error=True)
|
|
||||||
|
|
||||||
@unittest.skipIf(sys.platform.startswith('openbsd'),
|
@unittest.skipIf(sys.platform.startswith('openbsd'),
|
||||||
"Issue #12868: sigaltstack() doesn't work on "
|
"Issue #12868: sigaltstack() doesn't work on "
|
||||||
|
|
|
@ -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[] = {
|
static PyMethodDef TestMethods[] = {
|
||||||
{"raise_exception", raise_exception, METH_VARARGS},
|
{"raise_exception", raise_exception, METH_VARARGS},
|
||||||
{"raise_memoryerror", raise_memoryerror, METH_NOARGS},
|
{"raise_memoryerror", raise_memoryerror, METH_NOARGS},
|
||||||
|
@ -5938,6 +5959,8 @@ static PyMethodDef TestMethods[] = {
|
||||||
{"without_gc", without_gc, METH_O},
|
{"without_gc", without_gc, METH_O},
|
||||||
{"test_set_type_size", test_set_type_size, METH_NOARGS},
|
{"test_set_type_size", test_set_type_size, METH_NOARGS},
|
||||||
{"test_refcount", test_refcount, 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 */
|
{NULL, NULL} /* sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
#include "pycore_initconfig.h"
|
#include "pycore_initconfig.h" // _PyStatus_ERR
|
||||||
#include "pycore_traceback.h"
|
#include "pycore_traceback.h" // _Py_DumpTracebackThreads
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <object.h>
|
#include <object.h>
|
||||||
#include <frameobject.h>
|
#include <frameobject.h>
|
||||||
|
@ -1123,25 +1123,6 @@ faulthandler_sigabrt(PyObject *self, PyObject *args)
|
||||||
Py_RETURN_NONE;
|
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)
|
#if defined(FAULTHANDLER_USE_ALT_STACK)
|
||||||
#define FAULTHANDLER_STACK_OVERFLOW
|
#define FAULTHANDLER_STACK_OVERFLOW
|
||||||
|
|
||||||
|
@ -1278,8 +1259,6 @@ static PyMethodDef module_methods[] = {
|
||||||
PyDoc_STR("_sigabrt(): raise a SIGABRT signal")},
|
PyDoc_STR("_sigabrt(): raise a SIGABRT signal")},
|
||||||
{"_sigfpe", (PyCFunction)faulthandler_sigfpe, METH_NOARGS,
|
{"_sigfpe", (PyCFunction)faulthandler_sigfpe, METH_NOARGS,
|
||||||
PyDoc_STR("_sigfpe(): raise a SIGFPE signal")},
|
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
|
#ifdef FAULTHANDLER_STACK_OVERFLOW
|
||||||
{"_stack_overflow", faulthandler_stack_overflow, METH_NOARGS,
|
{"_stack_overflow", faulthandler_stack_overflow, METH_NOARGS,
|
||||||
PyDoc_STR("_stack_overflow(): recursive call to raise a stack overflow")},
|
PyDoc_STR("_stack_overflow(): recursive call to raise a stack overflow")},
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue