mirror of
https://github.com/python/cpython.git
synced 2025-10-18 12:48:57 +00:00
gh-129502: Fix handling errors in ctypes callbacks (GH-129504)
Unlikely errors in preparing arguments for ctypes callback are now handled in the same way as errors raised in the callback of in converting the result of the callback -- using sys.unraisablehook() instead of sys.excepthook() and not setting sys.last_exc and other variables.
This commit is contained in:
parent
3447f4a56a
commit
9d63ae5fe5
2 changed files with 35 additions and 36 deletions
|
@ -0,0 +1,5 @@
|
||||||
|
Unlikely errors in preparing arguments for :mod:`ctypes` callback are now
|
||||||
|
handled in the same way as errors raised in the callback of in converting
|
||||||
|
the result of the callback -- using :func:`sys.unraisablehook` instead of
|
||||||
|
:func:`sys.excepthook` and not setting :data:`sys.last_exc` and other
|
||||||
|
variables.
|
|
@ -81,22 +81,6 @@ PyType_Spec cthunk_spec = {
|
||||||
|
|
||||||
/**************************************************************/
|
/**************************************************************/
|
||||||
|
|
||||||
static void
|
|
||||||
PrintError(const char *msg, ...)
|
|
||||||
{
|
|
||||||
char buf[512];
|
|
||||||
PyObject *f = PySys_GetObject("stderr");
|
|
||||||
va_list marker;
|
|
||||||
|
|
||||||
va_start(marker, msg);
|
|
||||||
PyOS_vsnprintf(buf, sizeof(buf), msg, marker);
|
|
||||||
va_end(marker);
|
|
||||||
if (f != NULL && f != Py_None)
|
|
||||||
PyFile_WriteString(buf, f);
|
|
||||||
PyErr_Print();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef MS_WIN32
|
#ifdef MS_WIN32
|
||||||
/*
|
/*
|
||||||
* We must call AddRef() on non-NULL COM pointers we receive as arguments
|
* We must call AddRef() on non-NULL COM pointers we receive as arguments
|
||||||
|
@ -108,26 +92,23 @@ PrintError(const char *msg, ...)
|
||||||
* after checking for PyObject_IsTrue(), but this would probably be somewhat
|
* after checking for PyObject_IsTrue(), but this would probably be somewhat
|
||||||
* slower.
|
* slower.
|
||||||
*/
|
*/
|
||||||
static void
|
static int
|
||||||
TryAddRef(PyObject *cnv, CDataObject *obj)
|
TryAddRef(PyObject *cnv, CDataObject *obj)
|
||||||
{
|
{
|
||||||
IUnknown *punk;
|
IUnknown *punk;
|
||||||
PyObject *attrdict = _PyType_GetDict((PyTypeObject *)cnv);
|
PyObject *attrdict = _PyType_GetDict((PyTypeObject *)cnv);
|
||||||
if (!attrdict) {
|
if (!attrdict) {
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
int r = PyDict_Contains(attrdict, &_Py_ID(_needs_com_addref_));
|
int r = PyDict_Contains(attrdict, &_Py_ID(_needs_com_addref_));
|
||||||
if (r <= 0) {
|
if (r <= 0) {
|
||||||
if (r < 0) {
|
return r;
|
||||||
PrintError("getting _needs_com_addref_");
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
punk = *(IUnknown **)obj->b_ptr;
|
punk = *(IUnknown **)obj->b_ptr;
|
||||||
if (punk)
|
if (punk)
|
||||||
punk->lpVtbl->AddRef(punk);
|
punk->lpVtbl->AddRef(punk);
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -162,14 +143,13 @@ static void _CallPythonObject(ctypes_state *st,
|
||||||
|
|
||||||
StgInfo *info;
|
StgInfo *info;
|
||||||
if (PyStgInfo_FromType(st, cnv, &info) < 0) {
|
if (PyStgInfo_FromType(st, cnv, &info) < 0) {
|
||||||
goto Done;
|
goto Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info && info->getfunc && !_ctypes_simple_instance(st, cnv)) {
|
if (info && info->getfunc && !_ctypes_simple_instance(st, cnv)) {
|
||||||
PyObject *v = info->getfunc(*pArgs, info->size);
|
PyObject *v = info->getfunc(*pArgs, info->size);
|
||||||
if (!v) {
|
if (!v) {
|
||||||
PrintError("create argument %zd:\n", i);
|
goto Error;
|
||||||
goto Done;
|
|
||||||
}
|
}
|
||||||
args[i] = v;
|
args[i] = v;
|
||||||
/* XXX XXX XX
|
/* XXX XXX XX
|
||||||
|
@ -182,24 +162,25 @@ static void _CallPythonObject(ctypes_state *st,
|
||||||
/* Hm, shouldn't we use PyCData_AtAddress() or something like that instead? */
|
/* Hm, shouldn't we use PyCData_AtAddress() or something like that instead? */
|
||||||
CDataObject *obj = (CDataObject *)_PyObject_CallNoArgs(cnv);
|
CDataObject *obj = (CDataObject *)_PyObject_CallNoArgs(cnv);
|
||||||
if (!obj) {
|
if (!obj) {
|
||||||
PrintError("create argument %zd:\n", i);
|
goto Error;
|
||||||
goto Done;
|
|
||||||
}
|
}
|
||||||
if (!CDataObject_Check(st, obj)) {
|
if (!CDataObject_Check(st, obj)) {
|
||||||
|
PyErr_Format(PyExc_TypeError,
|
||||||
|
"%R returned unexpected result of type %T", cnv, obj);
|
||||||
Py_DECREF(obj);
|
Py_DECREF(obj);
|
||||||
PrintError("unexpected result of create argument %zd:\n", i);
|
goto Error;
|
||||||
goto Done;
|
|
||||||
}
|
}
|
||||||
memcpy(obj->b_ptr, *pArgs, info->size);
|
memcpy(obj->b_ptr, *pArgs, info->size);
|
||||||
args[i] = (PyObject *)obj;
|
args[i] = (PyObject *)obj;
|
||||||
#ifdef MS_WIN32
|
#ifdef MS_WIN32
|
||||||
TryAddRef(cnv, obj);
|
if (TryAddRef(cnv, obj) < 0) {
|
||||||
|
goto Error;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
PyErr_SetString(PyExc_TypeError,
|
PyErr_Format(PyExc_TypeError,
|
||||||
"cannot build parameter");
|
"cannot build parameter of type %R", cnv);
|
||||||
PrintError("Parsing argument %zd\n", i);
|
goto Error;
|
||||||
goto Done;
|
|
||||||
}
|
}
|
||||||
/* XXX error handling! */
|
/* XXX error handling! */
|
||||||
pArgs++;
|
pArgs++;
|
||||||
|
@ -207,8 +188,13 @@ static void _CallPythonObject(ctypes_state *st,
|
||||||
|
|
||||||
if (flags & (FUNCFLAG_USE_ERRNO | FUNCFLAG_USE_LASTERROR)) {
|
if (flags & (FUNCFLAG_USE_ERRNO | FUNCFLAG_USE_LASTERROR)) {
|
||||||
error_object = _ctypes_get_errobj(st, &space);
|
error_object = _ctypes_get_errobj(st, &space);
|
||||||
if (error_object == NULL)
|
if (error_object == NULL) {
|
||||||
|
PyErr_FormatUnraisable(
|
||||||
|
"Exception ignored while setting error for "
|
||||||
|
"ctypes callback function %R",
|
||||||
|
callable);
|
||||||
goto Done;
|
goto Done;
|
||||||
|
}
|
||||||
if (flags & FUNCFLAG_USE_ERRNO) {
|
if (flags & FUNCFLAG_USE_ERRNO) {
|
||||||
int temp = space[0];
|
int temp = space[0];
|
||||||
space[0] = errno;
|
space[0] = errno;
|
||||||
|
@ -295,6 +281,14 @@ static void _CallPythonObject(ctypes_state *st,
|
||||||
for (j = 0; j < i; j++) {
|
for (j = 0; j < i; j++) {
|
||||||
Py_DECREF(args[j]);
|
Py_DECREF(args[j]);
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
|
|
||||||
|
Error:
|
||||||
|
PyErr_FormatUnraisable(
|
||||||
|
"Exception ignored while creating argument %zd for "
|
||||||
|
"ctypes callback function %R",
|
||||||
|
i, callable);
|
||||||
|
goto Done;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void closure_fcn(ffi_cif *cif,
|
static void closure_fcn(ffi_cif *cif,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue