Skip Menu |

This queue is for tickets about the Inline-Python CPAN distribution.

Report information
The Basics
Id: 38895
Status: resolved
Priority: 0/
Queue: Inline-Python

People
Owner: Nobody in particular
Requestors: nine [...] detonation.org
Cc:
AdminCc:

Bug Information
Severity: Important
Broken in: 0.22
Fixed in: (no value)



Subject: memory leaks and segfaults
Inline::Python is leaking memory like pretty much all objects one moves from perl to Python space. I've fixed a bug where a perl object is freed when it's still in use, three memory leaks and a segfault that surfaced when some destructors finally got called, but there are still more segfaults seemingly unrelated to the code I changed and I'm not even sure if I cought all memory leaks. What I've found so far: PerlObj_dealloc should use sv_2mortal instead of SvREFCNT_dec, because the perl object could be a return value and thus still be in use. py_call_function and py_call_method both do not free the return value if called in void context and they only free the constructed argument tuple if a Python error occured, but not if everything worked. After fixing that PerlSub_dealloc segfaulted because of uninitialized member variables (sub, pkg and full). Py2Pl should sv_2mortal the newly created Inline::Python::Object. Otherwise it's refcnt would be 2 for a call like: my $obj = Inline::Python::Object->new('__main__', 'MyClass'); Unfortunately this creates a segfault in py_call_method in my application. Haven't tracked this down yet, thus the fix for the memleak is commented out in the patch.
Subject: Inline-Python-segfaults-memleaks.diff
diff -aur Inline-Python-0.22-mqoigh/Python.xs Inline-Python-0.22/Python.xs --- Inline-Python-0.22-mqoigh/Python.xs 2004-07-27 07:02:05.000000000 +0200 +++ Inline-Python-0.22/Python.xs 2008-08-29 22:18:39.000000000 +0200 @@ -213,12 +213,13 @@ } Printf(("calling func\n")); py_retval = PyObject_CallObject(func, tuple); + Py_XDECREF(func); +// Py_XDECREF(tuple); //FIXME: obviously correct, but causes segfault on second reload Printf(("received a response\n")); if (!py_retval || (PyErr_Occurred() != NULL)) { fprintf(stderr,"Error: Python error occurred:\n"); PyErr_Print(); - Py_XDECREF(tuple); - Py_XDECREF(func); + Py_XDECREF(tuple); //FIXME: should not be done only on errors croak("Error -- PyObject_CallObject(...) failed.\n"); XSRETURN_EMPTY; } @@ -234,8 +235,10 @@ /* For whatever reason, GIMME_V always returns G_VOID when we get forwarded * from eval_python(). */ - if (GIMME_V == G_VOID) + if (GIMME_V == G_VOID) { + Py_DECREF(py_retval); XSRETURN_EMPTY; + } #endif Printf(("calling Py2Pl\n")); @@ -321,11 +324,11 @@ Printf(("calling func\n")); py_retval = PyObject_CallObject(method, tuple); + Py_DECREF(tuple); + Py_DECREF(method); Printf(("received a response\n")); if (!py_retval || (PyErr_Occurred() != NULL)) { PyErr_Print(); - Py_DECREF(tuple); - Py_DECREF(method); croak("PyObject_CallObject(...) failed.\n"); XSRETURN_EMPTY; } @@ -333,8 +336,10 @@ Printf(("no error\n")); #ifdef CHECK_CONTEXT /* We can save a little time by checking our context */ - if (GIMME_V == G_VOID) + if (GIMME_V == G_VOID) { + Py_DECREF(py_retval); XSRETURN_EMPTY; + } #endif Printf(("calling Py2Pl()\n")); diff -aur Inline-Python-0.22-mqoigh/perlmodule.c Inline-Python-0.22/perlmodule.c --- Inline-Python-0.22-mqoigh/perlmodule.c 2001-12-10 06:18:09.000000000 +0100 +++ Inline-Python-0.22/perlmodule.c 2008-08-29 21:52:52.000000000 +0200 @@ -203,7 +203,7 @@ PerlObj_dealloc(PerlObj_object *self) { Py_XDECREF(self->pkg); - if (self->obj) SvREFCNT_dec(self->obj); + if (self->obj) sv_2mortal(self->obj); // mortal instead of DECREF. Object might be return value PyMem_DEL(self); } @@ -301,6 +301,11 @@ self->pkg = package; self->full = PyString_FromString(str); } + else { + self->sub = NULL; + self->pkg = NULL; + self->full = NULL; + } /* we don't have to check for errors because we shouldn't have been * created unless perl_get_cv worked once. diff -aur Inline-Python-0.22-mqoigh/py2pl.c Inline-Python-0.22/py2pl.c --- Inline-Python-0.22-mqoigh/py2pl.c 2005-01-10 07:19:33.000000000 +0100 +++ Inline-Python-0.22/py2pl.c 2008-08-29 22:02:28.000000000 +0200 @@ -102,6 +102,9 @@ re-bless it */ Py_INCREF(obj); Printf(("Py2Pl: Instance\n")); + /* this should be correct, but I get segfaults on method calls + with it :( */ + // sv_2mortal(inst_ptr); return inst_ptr; }
Fixed (along with countless other bugs of this type) in the newest version.