/* Handle cleanup of allocated memory in case of exception */
+static void
+cleanup_ptr(void *ptr)
+{
+ PyMem_FREE(ptr);
+}
+
+static void
+cleanup_buffer(void *ptr)
+{
+ PyBuffer_Release((Py_buffer *) ptr);
+}
+
static int
-addcleanup(void *ptr, PyObject **freelist)
+addcleanup(void *ptr, PyObject **freelist, void (*destr)(void *))
{
PyObject *cobj;
if (!*freelist) {
*freelist = PyList_New(0);
if (!*freelist) {
- PyMem_FREE(ptr);
+ destr(ptr);
return -1;
}
}
- cobj = PyCObject_FromVoidPtr(ptr, NULL);
+ cobj = PyCObject_FromVoidPtr(ptr, destr);
if (!cobj) {
- PyMem_FREE(ptr);
+ destr(ptr);
return -1;
}
if (PyList_Append(*freelist, cobj)) {
- PyMem_FREE(ptr);
Py_DECREF(cobj);
return -1;
}
static int
cleanreturn(int retval, PyObject *freelist)
{
- if (freelist) {
- if (retval == 0) {
- Py_ssize_t len = PyList_GET_SIZE(freelist), i;
- for (i = 0; i < len; i++)
- PyMem_FREE(PyCObject_AsVoidPtr(
- PyList_GET_ITEM(freelist, i)));
- }
- Py_DECREF(freelist);
- }
+ if (freelist && retval != 0) {
+ /* We were successful, reset the destructors so that they
+ don't get called. */
+ Py_ssize_t len = PyList_GET_SIZE(freelist), i;
+ for (i = 0; i < len; i++)
+ ((PyCObject *) PyList_GET_ITEM(freelist, i))
+ ->destructor = NULL;
+ }
+ Py_XDECREF(freelist);
return retval;
}
if (getbuffer(arg, p, &buf) < 0)
return converterr(buf, arg, msgbuf, bufsize);
}
+ if (addcleanup(p, freelist, cleanup_buffer)) {
+ return converterr(
+ "(cleanup problem)",
+ arg, msgbuf, bufsize);
+ }
format++;
} else if (*format == '#') {
void **p = (void **)va_arg(*p_va, char **);
if (getbuffer(arg, (Py_buffer*)p, &buf) < 0)
return converterr(buf, arg, msgbuf, bufsize);
format++;
+ if (addcleanup(p, freelist, cleanup_buffer)) {
+ return converterr(
+ "(cleanup problem)",
+ arg, msgbuf, bufsize);
+ }
break;
}
count = convertbuffer(arg, p, &buf);
if (getbuffer(arg, p, &buf) < 0)
return converterr(buf, arg, msgbuf, bufsize);
}
+ if (addcleanup(p, freelist, cleanup_buffer)) {
+ return converterr(
+ "(cleanup problem)",
+ arg, msgbuf, bufsize);
+ }
format++;
} else if (*format == '#') { /* any buffer-like object */
void **p = (void **)va_arg(*p_va, char **);
"(memory error)",
arg, msgbuf, bufsize);
}
- if (addcleanup(*buffer, freelist)) {
+ if (addcleanup(*buffer, freelist, cleanup_ptr)) {
Py_DECREF(s);
return converterr(
"(cleanup problem)",
return converterr("(memory error)",
arg, msgbuf, bufsize);
}
- if (addcleanup(*buffer, freelist)) {
+ if (addcleanup(*buffer, freelist, cleanup_ptr)) {
Py_DECREF(s);
return converterr("(cleanup problem)",
arg, msgbuf, bufsize);
PyErr_Clear();
return converterr("read-write buffer", arg, msgbuf, bufsize);
}
+ if (addcleanup(p, freelist, cleanup_buffer)) {
+ return converterr(
+ "(cleanup problem)",
+ arg, msgbuf, bufsize);
+ }
if (!PyBuffer_IsContiguous((Py_buffer*)p, 'C'))
return converterr("contiguous buffer", arg, msgbuf, bufsize);
break;