diff -r 6547f57561e8 Include/cobject.h --- a/Include/cobject.h Mon Aug 25 05:55:03 2008 +0200 +++ b/Include/cobject.h Mon Aug 25 14:29:50 2008 +0200 @@ -48,6 +48,15 @@ /* Modify a C object. Fails (==0) if object has a destructor. */ PyAPI_FUNC(int) PyCObject_SetVoidPtr(PyObject *self, void *cobj); + +typedef struct { + PyObject_HEAD + void *cobject; + void *desc; + void (*destructor)(void *); +} PyCObject; + + #ifdef __cplusplus } #endif diff -r 6547f57561e8 Objects/cobject.c --- a/Objects/cobject.c Mon Aug 25 05:55:03 2008 +0200 +++ b/Objects/cobject.c Mon Aug 25 14:29:50 2008 +0200 @@ -8,13 +8,6 @@ typedef void (*destructor1)(void *); typedef void (*destructor2)(void *, void*); - -typedef struct { - PyObject_HEAD - void *cobject; - void *desc; - void (*destructor)(void *); -} PyCObject; PyObject * PyCObject_FromVoidPtr(void *cobj, void (*destr)(void *)) diff -r 6547f57561e8 Python/getargs.c --- a/Python/getargs.c Mon Aug 25 05:55:03 2008 +0200 +++ b/Python/getargs.c Mon Aug 25 14:29:50 2008 +0200 @@ -139,8 +139,20 @@ /* 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) { @@ -150,13 +162,14 @@ return -1; } } - cobj = PyCObject_FromVoidPtr(ptr, NULL); + if (destr == NULL) + destr = cleanup_ptr; + 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; } @@ -167,16 +180,15 @@ 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); - } - return retval; + 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; } @@ -807,6 +819,7 @@ if (getbuffer(arg, p, &buf) < 0) return converterr(buf, arg, msgbuf, bufsize); } + addcleanup(p, freelist, cleanup_buffer); format++; } else if (*format == '#') { void **p = (void **)va_arg(*p_va, char **); @@ -856,6 +869,7 @@ if (getbuffer(arg, (Py_buffer*)p, &buf) < 0) return converterr(buf, arg, msgbuf, bufsize); format++; + addcleanup(p, freelist, cleanup_buffer); break; } count = convertbuffer(arg, p, &buf); @@ -889,6 +903,7 @@ if (getbuffer(arg, p, &buf) < 0) return converterr(buf, arg, msgbuf, bufsize); } + addcleanup(p, freelist, cleanup_buffer); format++; } else if (*format == '#') { /* any buffer-like object */ void **p = (void **)va_arg(*p_va, char **); @@ -1094,7 +1109,7 @@ "(memory error)", arg, msgbuf, bufsize); } - if (addcleanup(*buffer, freelist)) { + if (addcleanup(*buffer, freelist, NULL)) { Py_DECREF(s); return converterr( "(cleanup problem)", @@ -1136,7 +1151,7 @@ return converterr("(memory error)", arg, msgbuf, bufsize); } - if (addcleanup(*buffer, freelist)) { + if (addcleanup(*buffer, freelist, NULL)) { Py_DECREF(s); return converterr("(cleanup problem)", arg, msgbuf, bufsize); @@ -1251,6 +1266,7 @@ } if (!PyBuffer_IsContiguous((Py_buffer*)p, 'C')) return converterr("contiguous buffer", arg, msgbuf, bufsize); + addcleanup(p, freelist, cleanup_buffer); break; }