Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 86451b1

Browse files
[3.12] gh-129502: Fix handling errors in ctypes callbacks (GH-129504) (#129639)
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. (cherry picked from commit 9d63ae5)
1 parent 4879257 commit 86451b1

File tree

2 files changed

+31
-34
lines changed

2 files changed

+31
-34
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Unlikely errors in preparing arguments for :mod:`ctypes` callback are now
2+
handled in the same way as errors raised in the callback of in converting
3+
the result of the callback -- using :func:`sys.unraisablehook` instead of
4+
:func:`sys.excepthook` and not setting :data:`sys.last_exc` and other
5+
variables.

Modules/_ctypes/callbacks.c

Lines changed: 26 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -82,22 +82,6 @@ PyType_Spec cthunk_spec = {
8282

8383
/**************************************************************/
8484

85-
static void
86-
PrintError(const char *msg, ...)
87-
{
88-
char buf[512];
89-
PyObject *f = PySys_GetObject("stderr");
90-
va_list marker;
91-
92-
va_start(marker, msg);
93-
PyOS_vsnprintf(buf, sizeof(buf), msg, marker);
94-
va_end(marker);
95-
if (f != NULL && f != Py_None)
96-
PyFile_WriteString(buf, f);
97-
PyErr_Print();
98-
}
99-
100-
10185
#ifdef MS_WIN32
10286
/*
10387
* We must call AddRef() on non-NULL COM pointers we receive as arguments
@@ -109,22 +93,19 @@ PrintError(const char *msg, ...)
10993
* after checking for PyObject_IsTrue(), but this would probably be somewhat
11094
* slower.
11195
*/
112-
static void
96+
static int
11397
TryAddRef(StgDictObject *dict, CDataObject *obj)
11498
{
11599
IUnknown *punk;
116100
int r = PyDict_Contains((PyObject *)dict, &_Py_ID(_needs_com_addref_));
117101
if (r <= 0) {
118-
if (r < 0) {
119-
PrintError("getting _needs_com_addref_");
120-
}
121-
return;
102+
return r;
122103
}
123104

124105
punk = *(IUnknown **)obj->b_ptr;
125106
if (punk)
126107
punk->lpVtbl->AddRef(punk);
127-
return;
108+
return 0;
128109
}
129110
#endif
130111

@@ -160,8 +141,7 @@ static void _CallPythonObject(void *mem,
160141
if (dict && dict->getfunc && !_ctypes_simple_instance(cnv)) {
161142
PyObject *v = dict->getfunc(*pArgs, dict->size);
162143
if (!v) {
163-
PrintError("create argument %zd:\n", i);
164-
goto Done;
144+
goto Error;
165145
}
166146
args[i] = v;
167147
/* XXX XXX XX
@@ -173,33 +153,38 @@ static void _CallPythonObject(void *mem,
173153
/* Hm, shouldn't we use PyCData_AtAddress() or something like that instead? */
174154
CDataObject *obj = (CDataObject *)_PyObject_CallNoArgs(cnv);
175155
if (!obj) {
176-
PrintError("create argument %zd:\n", i);
177-
goto Done;
156+
goto Error;
178157
}
179158
if (!CDataObject_Check(obj)) {
159+
PyErr_Format(PyExc_TypeError,
160+
"%R returned unexpected result of type %T", cnv, obj);
180161
Py_DECREF(obj);
181-
PrintError("unexpected result of create argument %zd:\n", i);
182-
goto Done;
162+
goto Error;
183163
}
184164
memcpy(obj->b_ptr, *pArgs, dict->size);
185165
args[i] = (PyObject *)obj;
186166
#ifdef MS_WIN32
187-
TryAddRef(dict, obj);
167+
if (TryAddRef(dict, obj) < 0) {
168+
goto Error;
169+
}
188170
#endif
189171
} else {
190-
PyErr_SetString(PyExc_TypeError,
191-
"cannot build parameter");
192-
PrintError("Parsing argument %zd\n", i);
193-
goto Done;
172+
PyErr_Format(PyExc_TypeError,
173+
"cannot build parameter of type %R", cnv);
174+
goto Error;
194175
}
195176
/* XXX error handling! */
196177
pArgs++;
197178
}
198179

199180
if (flags & (FUNCFLAG_USE_ERRNO | FUNCFLAG_USE_LASTERROR)) {
200181
error_object = _ctypes_get_errobj(&space);
201-
if (error_object == NULL)
182+
if (error_object == NULL) {
183+
_PyErr_WriteUnraisableMsg("while setting error for "
184+
"ctypes callback function",
185+
callable);
202186
goto Done;
187+
}
203188
if (flags & FUNCFLAG_USE_ERRNO) {
204189
int temp = space[0];
205190
space[0] = errno;
@@ -284,6 +269,13 @@ static void _CallPythonObject(void *mem,
284269
Py_DECREF(args[j]);
285270
}
286271
PyGILState_Release(state);
272+
return;
273+
274+
Error:
275+
_PyErr_WriteUnraisableMsg("while creating argument for "
276+
"ctypes callback function",
277+
callable);
278+
goto Done;
287279
}
288280

289281
static void closure_fcn(ffi_cif *cif,

0 commit comments

Comments
 (0)