8000 bpo-46323: Reduce stack usage of ctypes python callback function. (GH… · python/cpython@d18120c · GitHub
[go: up one dir, main page]

Skip to content

Commit d18120c

Browse files
authored
bpo-46323: Reduce stack usage of ctypes python callback function. (GH-31224)
1 parent bf2d44f commit d18120c

File tree

3 files changed

+17
-27
lines changed

3 files changed

+17
-27
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
:mod:`ctypes` now allocates memory on the stack instead of on the heap
2+
to pass arguments while calling a Python callback function.
3+
Patch by Dong-hee Na.

Modules/_ctypes/callbacks.c

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,18 @@
1414

1515
#include <stdbool.h>
1616

17+
#ifdef MS_WIN32
18+
# include <malloc.h>
19+
#endif
20+
1721
#include <ffi.h>
1822
#include "ctypes.h"
1923

24+
#ifdef HAVE_ALLOCA_H
25+
/* AIX needs alloca.h for alloca() */
26+
#include <alloca.h>
27+
#endif
28+
2029
/**************************************************************/
2130

2231
static void
@@ -148,32 +157,17 @@ static void _CallPythonObject(void *mem,
148157
void **pArgs)
149158
{
150159
PyObject *result = NULL;
151-
PyObject **args = NULL;
152160
Py_ssize_t i = 0, j = 0, nargs = 0;
153161
PyObject *error_object = NULL;
154162
int *space;
155163
PyGILState_STATE state = PyGILState_Ensure();
156164

157165
assert(PyTuple_Check(converters));
158166
nargs = PyTuple_GET_SIZE(converters);
159-
/* Hm. What to return in case of error?
160-
For COM, 0xFFFFFFFF seems better than 0.
161-
*/
162-
if (nargs < 0) {
163-
PrintError("BUG: PySequence_Length");
164-
goto Done;
165-
}
166-
167-
PyObject *args_stack[CTYPES_MAX_ARGCOUNT];
168-
if (nargs <= CTYPES_MAX_ARGCOUNT) {
169-
args = args_stack;
170-
}
171-
else {
172-
args = PyMem_Malloc(nargs * sizeof(PyObject *));
173-
if (args == NULL) {
174-
PyErr_NoMemory();
175-
goto Done;
176-
}
167+
assert(nargs <= CTYPES_MAX_ARGCOUNT);
168+
PyObject **args = NULL;
169+
if (nargs > 0) {
170+
args = alloca(nargs * sizeof(PyObject *));
177171
}
178172

179173
PyObject **cnvs = PySequence_Fast_ITEMS(converters);
@@ -310,9 +304,6 @@ static void _CallPythonObject(void *mem,
310304
for (j = 0; j < i; j++) {
311305
Py_DECREF(args[j]);
312306
}
313-
if (args != args_stack) {
314-
PyMem_Free(args);
315-
}
316307
PyGILState_Release(state);
317308
}
318309

Modules/_ctypes/callproc.c

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1162,11 +1162,7 @@ PyObject *_ctypes_callproc(PPROC pProc,
11621162
return NULL;
11631163
}
11641164

1165-
args = (struct argument *)alloca(sizeof(struct argument) * argcount);
1166-
if (!args) {
1167-
PyErr_NoMemory();
1168-
return NULL;
1169-
}
1165+
args = alloca(sizeof(struct argument) * argcount);
11701166
memset(args, 0, sizeof(struct argument) * argcount);
11711167
argtype_count = argtypes ? PyTuple_GET_SIZE(argtypes) : 0;
11721168
#ifdef MS_WIN32

0 commit comments

Comments
 (0)
0