From 676593859e75d4c3543d143092b77f55389006e4 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 5 Sep 2023 01:54:55 +0200 Subject: [PATCH] gh-106320: Remove private _PyErr_WriteUnraisableMsg() (#108863) Move the private _PyErr_WriteUnraisableMsg() functions to the internal C API (pycore_pyerrors.h). Move write_unraisable_exc() from _testcapi to _testinternalcapi. --- Include/cpython/pyerrors.h | 4 --- Include/internal/pycore_pyerrors.h | 5 ++++ Lib/test/audit-tests.py | 2 +- Lib/test/test_sys.py | 4 +-- Modules/_ctypes/_ctypes.c | 1 + Modules/_ctypes/callbacks.c | 6 ++--- Modules/_lsprof.c | 2 ++ Modules/_testcapi/clinic/exceptions.c.h | 34 +------------------------ Modules/_testcapi/exceptions.c | 31 ---------------------- Modules/_testinternalcapi.c | 33 +++++++++++++++++++++++- Modules/_threadmodule.c | 1 + Modules/atexitmodule.c | 3 ++- Modules/clinic/_testinternalcapi.c.h | 34 ++++++++++++++++++++++++- Modules/getpath.c | 1 + Python/compile.c | 1 + Python/perf_trampoline.c | 1 + 16 files changed, 86 insertions(+), 77 deletions(-) diff --git a/Include/cpython/pyerrors.h b/Include/cpython/pyerrors.h index 9633a5407f28a6..da96eec4b35aab 100644 --- a/Include/cpython/pyerrors.h +++ b/Include/cpython/pyerrors.h @@ -116,10 +116,6 @@ PyAPI_FUNC(PyObject *) PyErr_ProgramTextObject( PyObject *filename, int lineno); -PyAPI_FUNC(void) _PyErr_WriteUnraisableMsg( - const char *err_msg, - PyObject *obj); - PyAPI_FUNC(void) _Py_NO_RETURN _Py_FatalErrorFunc( const char *func, const char *message); diff --git a/Include/internal/pycore_pyerrors.h b/Include/internal/pycore_pyerrors.h index 0f16fb894d17e1..184eb35e52b47b 100644 --- a/Include/internal/pycore_pyerrors.h +++ b/Include/internal/pycore_pyerrors.h @@ -170,6 +170,11 @@ Py_DEPRECATED(3.12) extern void _PyErr_ChainExceptions(PyObject *, PyObject *, P // Export for '_zoneinfo' shared extension PyAPI_FUNC(void) _PyErr_ChainExceptions1(PyObject *); +// Export for '_lsprof' shared extension +PyAPI_FUNC(void) _PyErr_WriteUnraisableMsg( + const char *err_msg, + PyObject *obj); + #ifdef __cplusplus } #endif diff --git a/Lib/test/audit-tests.py b/Lib/test/audit-tests.py index ad8f72f556331d..f14c2635d39390 100644 --- a/Lib/test/audit-tests.py +++ b/Lib/test/audit-tests.py @@ -289,7 +289,7 @@ def hook(event, args): def test_unraisablehook(): - from _testcapi import write_unraisable_exc + from _testinternalcapi import write_unraisable_exc def unraisablehook(hookargs): pass diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index d8b684c8a008f0..e8a99244a3a28d 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -1199,11 +1199,11 @@ class MyType: @test.support.cpython_only class UnraisableHookTest(unittest.TestCase): def write_unraisable_exc(self, exc, err_msg, obj): - import _testcapi + import _testinternalcapi import types err_msg2 = f"Exception ignored {err_msg}" try: - _testcapi.write_unraisable_exc(exc, err_msg, obj) + _testinternalcapi.write_unraisable_exc(exc, err_msg, obj) return types.SimpleNamespace(exc_type=type(exc), exc_value=exc, exc_traceback=exc.__traceback__, diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 3af3a80bfb5e95..184af2132c2707 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -110,6 +110,7 @@ bytes(cdata) #include "pycore_call.h" // _PyObject_CallNoArgs() #include "pycore_ceval.h" // _Py_EnterRecursiveCall() +#include "pycore_pyerrors.h" // _PyErr_WriteUnraisableMsg() #include diff --git a/Modules/_ctypes/callbacks.c b/Modules/_ctypes/callbacks.c index 0d8ecce009a67a..1bd8fec97179e9 100644 --- a/Modules/_ctypes/callbacks.c +++ b/Modules/_ctypes/callbacks.c @@ -8,9 +8,9 @@ # include #endif -#include "pycore_call.h" // _PyObject_CallNoArgs() -#include "pycore_runtime.h" // _PyRuntime -#include "pycore_global_objects.h" // _Py_ID() +#include "pycore_call.h" // _PyObject_CallNoArgs() +#include "pycore_pyerrors.h" // _PyErr_WriteUnraisableMsg() +#include "pycore_runtime.h" // _Py_ID() #include diff --git a/Modules/_lsprof.c b/Modules/_lsprof.c index e7dcb6e1713212..d23a756ace887d 100644 --- a/Modules/_lsprof.c +++ b/Modules/_lsprof.c @@ -5,7 +5,9 @@ #include "Python.h" #include "pycore_call.h" // _PyObject_CallNoArgs() #include "pycore_ceval.h" // _PyEval_SetProfile() +#include "pycore_pyerrors.h" // _PyErr_WriteUnraisableMsg() #include "pycore_pystate.h" // _PyThreadState_GET() + #include "rotatingtree.h" /************************************************************/ diff --git a/Modules/_testcapi/clinic/exceptions.c.h b/Modules/_testcapi/clinic/exceptions.c.h index 01881534329c9d..39b5f8b91a00db 100644 --- a/Modules/_testcapi/clinic/exceptions.c.h +++ b/Modules/_testcapi/clinic/exceptions.c.h @@ -394,38 +394,6 @@ PyDoc_STRVAR(_testcapi_set_exception__doc__, #define _TESTCAPI_SET_EXCEPTION_METHODDEF \ {"set_exception", (PyCFunction)_testcapi_set_exception, METH_O, _testcapi_set_exception__doc__}, -PyDoc_STRVAR(_testcapi_write_unraisable_exc__doc__, -"write_unraisable_exc($module, exception, err_msg, obj, /)\n" -"--\n" -"\n"); - -#define _TESTCAPI_WRITE_UNRAISABLE_EXC_METHODDEF \ - {"write_unraisable_exc", _PyCFunction_CAST(_testcapi_write_unraisable_exc), METH_FASTCALL, _testcapi_write_unraisable_exc__doc__}, - -static PyObject * -_testcapi_write_unraisable_exc_impl(PyObject *module, PyObject *exc, - PyObject *err_msg, PyObject *obj); - -static PyObject * -_testcapi_write_unraisable_exc(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - PyObject *exc; - PyObject *err_msg; - PyObject *obj; - - if (!_PyArg_CheckPositional("write_unraisable_exc", nargs, 3, 3)) { - goto exit; - } - exc = args[0]; - err_msg = args[1]; - obj = args[2]; - return_value = _testcapi_write_unraisable_exc_impl(module, exc, err_msg, obj); - -exit: - return return_value; -} - PyDoc_STRVAR(_testcapi_traceback_print__doc__, "traceback_print($module, traceback, file, /)\n" "--\n" @@ -487,4 +455,4 @@ _testcapi_unstable_exc_prep_reraise_star(PyObject *module, PyObject *const *args exit: return return_value; } -/*[clinic end generated code: output=8f273949da28ffb5 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=ff19512450b3bbdb input=a9049054013a1b77]*/ diff --git a/Modules/_testcapi/exceptions.c b/Modules/_testcapi/exceptions.c index 025b42db247e81..b1388d75711774 100644 --- a/Modules/_testcapi/exceptions.c +++ b/Modules/_testcapi/exceptions.c @@ -278,36 +278,6 @@ _testcapi_set_exception(PyObject *module, PyObject *new_exc) return exc; } -/*[clinic input] -_testcapi.write_unraisable_exc - exception as exc: object - err_msg: object - obj: object - / -[clinic start generated code]*/ - -static PyObject * -_testcapi_write_unraisable_exc_impl(PyObject *module, PyObject *exc, - PyObject *err_msg, PyObject *obj) -/*[clinic end generated code: output=39827c5e0a8c2092 input=582498da5b2ee6cf]*/ -{ - - const char *err_msg_utf8; - if (err_msg != Py_None) { - err_msg_utf8 = PyUnicode_AsUTF8(err_msg); - if (err_msg_utf8 == NULL) { - return NULL; - } - } - else { - err_msg_utf8 = NULL; - } - - PyErr_SetObject((PyObject *)Py_TYPE(exc), exc); - _PyErr_WriteUnraisableMsg(err_msg_utf8, obj); - Py_RETURN_NONE; -} - /*[clinic input] _testcapi.traceback_print traceback: object @@ -384,7 +354,6 @@ static PyMethodDef test_methods[] = { _TESTCAPI_SET_EXC_INFO_METHODDEF _TESTCAPI_SET_EXCEPTION_METHODDEF _TESTCAPI_TRACEBACK_PRINT_METHODDEF - _TESTCAPI_WRITE_UNRAISABLE_EXC_METHODDEF _TESTCAPI_UNSTABLE_EXC_PREP_RERAISE_STAR_METHODDEF {NULL}, }; diff --git a/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c index 96d568294a9710..b6792e38fa98c2 100644 --- a/Modules/_testinternalcapi.c +++ b/Modules/_testinternalcapi.c @@ -26,7 +26,6 @@ #include "pycore_object.h" // _PyObject_IsFreed() #include "pycore_pathconfig.h" // _PyPathConfig_ClearGlobal() #include "pycore_pyerrors.h" // _PyErr_ChainExceptions1() -#include "pycore_pyerrors.h" // _Py_UTF8_Edit_Cost() #include "pycore_pystate.h" // _PyThreadState_GET() #include "interpreteridobject.h" // PyInterpreterID_LookUp() @@ -1448,6 +1447,37 @@ run_in_subinterp_with_config(PyObject *self, PyObject *args, PyObject *kwargs) } +/*[clinic input] +_testinternalcapi.write_unraisable_exc + exception as exc: object + err_msg: object + obj: object + / +[clinic start generated code]*/ + +static PyObject * +_testinternalcapi_write_unraisable_exc_impl(PyObject *module, PyObject *exc, + PyObject *err_msg, PyObject *obj) +/*[clinic end generated code: output=a0f063cdd04aad83 input=274381b1a3fa5cd6]*/ +{ + + const char *err_msg_utf8; + if (err_msg != Py_None) { + err_msg_utf8 = PyUnicode_AsUTF8(err_msg); + if (err_msg_utf8 == NULL) { + return NULL; + } + } + else { + err_msg_utf8 = NULL; + } + + PyErr_SetObject((PyObject *)Py_TYPE(exc), exc); + _PyErr_WriteUnraisableMsg(err_msg_utf8, obj); + Py_RETURN_NONE; +} + + static PyMethodDef module_functions[] = { {"get_configs", get_configs, METH_NOARGS}, {"get_recursion_depth", get_recursion_depth, METH_NOARGS}, @@ -1503,6 +1533,7 @@ static PyMethodDef module_functions[] = { {"run_in_subinterp_with_config", _PyCFunction_CAST(run_in_subinterp_with_config), METH_VARARGS | METH_KEYWORDS}, + _TESTINTERNALCAPI_WRITE_UNRAISABLE_EXC_METHODDEF {NULL, NULL} /* sentinel */ }; diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c index 2cf866c5a11416..49f34fcb9feb70 100644 --- a/Modules/_threadmodule.c +++ b/Modules/_threadmodule.c @@ -7,6 +7,7 @@ #include "pycore_dict.h" // _PyDict_Pop() #include "pycore_interp.h" // _PyInterpreterState.threads.count #include "pycore_moduleobject.h" // _PyModule_GetState() +#include "pycore_pyerrors.h" // _PyErr_WriteUnraisableMsg() #include "pycore_pylifecycle.h" #include "pycore_pystate.h" // _PyThreadState_SetCurrent() #include "pycore_sysmodule.h" // _PySys_GetAttr() diff --git a/Modules/atexitmodule.c b/Modules/atexitmodule.c index cec177cfc2f9c8..57e2ea67450453 100644 --- a/Modules/atexitmodule.c +++ b/Modules/atexitmodule.c @@ -7,9 +7,10 @@ */ #include "Python.h" -#include "pycore_atexit.h" +#include "pycore_atexit.h" // export _Py_AtExit() #include "pycore_initconfig.h" // _PyStatus_NO_MEMORY #include "pycore_interp.h" // PyInterpreterState.atexit +#include "pycore_pyerrors.h" // _PyErr_WriteUnraisableMsg() #include "pycore_pystate.h" // _PyInterpreterState_GET /* ===================================================================== */ diff --git a/Modules/clinic/_testinternalcapi.c.h b/Modules/clinic/_testinternalcapi.c.h index 28761387023508..38a3579d7dec77 100644 --- a/Modules/clinic/_testinternalcapi.c.h +++ b/Modules/clinic/_testinternalcapi.c.h @@ -264,4 +264,36 @@ _testinternalcapi_assemble_code_object(PyObject *module, PyObject *const *args, exit: return return_value; } -/*[clinic end generated code: output=cba1c94ff4015b82 input=a9049054013a1b77]*/ + +PyDoc_STRVAR(_testinternalcapi_write_unraisable_exc__doc__, +"write_unraisable_exc($module, exception, err_msg, obj, /)\n" +"--\n" +"\n"); + +#define _TESTINTERNALCAPI_WRITE_UNRAISABLE_EXC_METHODDEF \ + {"write_unraisable_exc", _PyCFunction_CAST(_testinternalcapi_write_unraisable_exc), METH_FASTCALL, _testinternalcapi_write_unraisable_exc__doc__}, + +static PyObject * +_testinternalcapi_write_unraisable_exc_impl(PyObject *module, PyObject *exc, + PyObject *err_msg, PyObject *obj); + +static PyObject * +_testinternalcapi_write_unraisable_exc(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *exc; + PyObject *err_msg; + PyObject *obj; + + if (!_PyArg_CheckPositional("write_unraisable_exc", nargs, 3, 3)) { + goto exit; + } + exc = args[0]; + err_msg = args[1]; + obj = args[2]; + return_value = _testinternalcapi_write_unraisable_exc_impl(module, exc, err_msg, obj); + +exit: + return return_value; +} +/*[clinic end generated code: output=c7156622e80df1ce input=a9049054013a1b77]*/ diff --git a/Modules/getpath.c b/Modules/getpath.c index 71e23e1edaf11c..3b926cac0d3f24 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -4,6 +4,7 @@ #include "pycore_fileutils.h" // _Py_abspath() #include "pycore_initconfig.h" // _PyStatus_EXCEPTION() #include "pycore_pathconfig.h" // _PyPathConfig_ReadGlobal() +#include "pycore_pyerrors.h" // _PyErr_WriteUnraisableMsg() #include "pycore_pymem.h" // _PyMem_RawWcsdup() #include "marshal.h" // PyMarshal_ReadObjectFromString diff --git a/Python/compile.c b/Python/compile.c index 50e29b4607f7ce..ae9edc90ea4367 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -34,6 +34,7 @@ #include "pycore_flowgraph.h" #include "pycore_intrinsics.h" #include "pycore_long.h" // _PyLong_GetZero() +#include "pycore_pyerrors.h" // _PyErr_WriteUnraisableMsg() #include "pycore_pystate.h" // _Py_GetConfig() #include "pycore_setobject.h" // _PySet_NextEntry() #include "pycore_symtable.h" // PySTEntryObject, _PyFuture_FromAST() diff --git a/Python/perf_trampoline.c b/Python/perf_trampoline.c index 10675bf9f8292a..0f1af30226d9fb 100644 --- a/Python/perf_trampoline.c +++ b/Python/perf_trampoline.c @@ -133,6 +133,7 @@ any DWARF information available for them). #include "pycore_ceval.h" #include "pycore_frame.h" #include "pycore_interp.h" +#include "pycore_pyerrors.h" // _PyErr_WriteUnraisableMsg() #ifdef PY_HAVE_PERF_TRAMPOLINE