-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Fix a memory leak when creating Python3 modules. #2024
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For my own understanding, what is module
in the lambda? Is that m_ptr
?
Also is the return value of PyModule_GetDef
the def
from a few lines above?
include/pybind11/pybind11.h
Outdated
@@ -799,7 +799,11 @@ class module : public object { | |||
def->m_name = name; | |||
def->m_doc = doc; | |||
def->m_size = -1; | |||
Py_INCREF(def); | |||
def->m_free = [](void* module ) { | |||
if (module != NULL) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can just be if (module)
. If you really want to be explicit in your bool expressions, use module != nullptr
.
include/pybind11/pybind11.h
Outdated
@@ -795,11 +795,17 @@ class module : public object { | |||
if (!options::show_user_defined_docstrings()) doc = nullptr; | |||
#if PY_MAJOR_VERSION >= 3 | |||
PyModuleDef *def = new PyModuleDef(); | |||
// Ensure that Python does not try to delete this. | |||
Py_INCREF(def); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's happening here? Why would the python allocator be trying to free memory that it has never allocated?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, this was me trying a theory on Travis, because I could not reproduce the failure locally even in Docker
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(My theory was wrong, anyway)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I didn't notice the travis failure before. I can still repro, though I get the same error as travis, but on pytest, not cpptest.
Hop over to gitter. It will be easier to chat there and look into this.
Yes, you're right - The issue here is that |
I think you will need to |
That would make That property of |
Either variant is fine with me, let's just not mix |
This turned out to be more tricky than anticipated. The current version is not meant to be merged as-is, but to share my current status for you to see. |
Any news here? Is anyone interested in picking up the work on this minor leak (which I understand can be rather annoying in the context of |
Yeah, I've worked on this with @T045T for a while in December. One approach fixes one version of python, other fixes two other versions of python, yadda yadda yadda... It seems like CPython API expects this thing to have static lifetime and different versions of python rely on that assumption in different ways. I don't think we can solve this leak by a cleverly placed Maybe valgrind users should just accept the Here's the suppression rule for python 3.6 compiled in debug mode:
|
EDIT: Forget what I've just said. I mixed something up. |
I just merged #2413 which solves the leak check issue in a different way. Closing this PR. Please let us know if you're still seeing leak check errors in your environment (seems very unlikely). |
With no segfaults, this time!