diff options
author | Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com> | 2020-05-27 23:00:01 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-05-27 23:00:01 (GMT) |
commit | 9e3c583954f75a6396d1935e000df85d89b78a3d (patch) | |
tree | 56c191b0ca8de9ab8a55ff5720c6a047f0b0b4e1 /Modules | |
parent | be240b857154078617cdd68fc63d1e48549e7a0b (diff) | |
download | cpython-9e3c583954f75a6396d1935e000df85d89b78a3d.zip cpython-9e3c583954f75a6396d1935e000df85d89b78a3d.tar.gz cpython-9e3c583954f75a6396d1935e000df85d89b78a3d.tar.bz2 |
bpo-40795: ctypes calls unraisablehook with an exception (GH-20452)
If ctypes fails to convert the result of a callback or if a ctypes
callback function raises an exception, sys.unraisablehook is now
called with an exception set. Previously, the error was logged into
stderr by PyErr_Print().
(cherry picked from commit 10228bad0452d94e66c964b625a0b61befa08e59)
Co-authored-by: Victor Stinner <vstinner@python.org>
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/_ctypes/callbacks.c | 43 | ||||
-rw-r--r-- | Modules/_ctypes/callproc.c | 2 |
2 files changed, 31 insertions, 14 deletions
diff --git a/Modules/_ctypes/callbacks.c b/Modules/_ctypes/callbacks.c index 2b903c9..29e8fac 100644 --- a/Modules/_ctypes/callbacks.c +++ b/Modules/_ctypes/callbacks.c @@ -213,9 +213,6 @@ static void _CallPythonObject(void *mem, pArgs++; } -#define CHECK(what, x) \ -if (x == NULL) _PyTraceback_Add(what, "_ctypes/callbacks.c", __LINE__ - 1), PyErr_Print() - if (flags & (FUNCFLAG_USE_ERRNO | FUNCFLAG_USE_LASTERROR)) { error_object = _ctypes_get_errobj(&space); if (error_object == NULL) @@ -235,7 +232,10 @@ if (x == NULL) _PyTraceback_Add(what, "_ctypes/callbacks.c", __LINE__ - 1), PyEr } result = PyObject_CallObject(callable, arglist); - CHECK("'calling callback function'", result); + if (result == NULL) { + _PyErr_WriteUnraisableMsg("on calling ctypes callback function", + callable); + } #ifdef MS_WIN32 if (flags & FUNCFLAG_USE_LASTERROR) { @@ -251,16 +251,17 @@ if (x == NULL) _PyTraceback_Add(what, "_ctypes/callbacks.c", __LINE__ - 1), PyEr } Py_XDECREF(error_object); - if ((restype != &ffi_type_void) && result) { - PyObject *keep; + if (restype != &ffi_type_void && result) { assert(setfunc); + #ifdef WORDS_BIGENDIAN - /* See the corresponding code in callproc.c, around line 961 */ - if (restype->type != FFI_TYPE_FLOAT && restype->size < sizeof(ffi_arg)) + /* See the corresponding code in _ctypes_callproc(): + in callproc.c, around line 1219. */ + if (restype->type != FFI_TYPE_FLOAT && restype->size < sizeof(ffi_arg)) { mem = (char *)mem + sizeof(ffi_arg) - restype->size; + } #endif - keep = setfunc(mem, result, 0); - CHECK("'converting callback result'", keep); + /* keep is an object we have to keep alive so that the result stays valid. If there is no such object, the setfunc will have returned Py_None. @@ -270,18 +271,32 @@ if (x == NULL) _PyTraceback_Add(what, "_ctypes/callbacks.c", __LINE__ - 1), PyEr be the result. EXCEPT when restype is py_object - Python itself knows how to manage the refcount of these objects. */ - if (keep == NULL) /* Could not convert callback result. */ - PyErr_WriteUnraisable(callable); - else if (keep == Py_None) /* Nothing to keep */ + PyObject *keep = setfunc(mem, result, 0); + + if (keep == NULL) { + /* Could not convert callback result. */ + _PyErr_WriteUnraisableMsg("on converting result " + "of ctypes callback function", + callable); + } + else if (keep == Py_None) { + /* Nothing to keep */ Py_DECREF(keep); + } else if (setfunc != _ctypes_get_fielddesc("O")->setfunc) { if (-1 == PyErr_WarnEx(PyExc_RuntimeWarning, "memory leak in callback function.", 1)) - PyErr_WriteUnraisable(callable); + { + _PyErr_WriteUnraisableMsg("on converting result " + "of ctypes callback function", + callable); + } } } + Py_XDECREF(result); + Done: Py_XDECREF(arglist); PyGILState_Release(state); diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c index 9bc28c2..af6e1e8 100644 --- a/Modules/_ctypes/callproc.c +++ b/Modules/_ctypes/callproc.c @@ -1231,7 +1231,9 @@ PyObject *_ctypes_callproc(PPROC pProc, if (rtype->type != FFI_TYPE_FLOAT && rtype->type != FFI_TYPE_STRUCT && rtype->size < sizeof(ffi_arg)) + { resbuf = (char *)resbuf + sizeof(ffi_arg) - rtype->size; + } #endif #ifdef MS_WIN32 |