Skip to content

Destroy internals if created during Py_Finalize() #892

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

Merged
merged 1 commit into from
Jun 8, 2017

Conversation

jagerman
Copy link
Member

@jagerman jagerman commented Jun 7, 2017

Py_Finalize could potentially invoke code that calls get_internals(),
which could create a new internals object if one didn't exist.
finalize_interpreter() didn't catch this because it only used the
pre-finalize interpreter pointer status; if this happens, it results in
the internals pointer not being properly destroyed with the interpreter,
which leaks, and also causes a get_internals() under a future
interpreter to return an internals object that is wrong in various ways.

The two lines added to embed.h are the fix; the rest is just adding a test case that triggers and detects the issue.

@jagerman
Copy link
Member Author

jagerman commented Jun 7, 2017

Cc @dean0x7d for confirmation that the fix looks good.

@jagerman jagerman force-pushed the internals-destroy-fix branch from f484d95 to dfa4238 Compare June 7, 2017 18:25
// didn't exist above. (But we still use the above because if nothing calls get_internals() we
// might not have the static pointer set in get_internals_ptr())
if (!internals_ptr_ptr)
internals_ptr_ptr = &detail::get_internals_ptr();
Copy link
Member

@dean0x7d dean0x7d Jun 8, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch! I'd suggest moving up get_internals_ptr() to mirror the code from detail:: get_internals(). This is invariant with respect to Py_Finalize():

auto **internals_ptr_ptr = &detail::get_internals_ptr();
if (builtins.contains(id) && isinstance<capsule>(builtins[id]))
    internals_ptr_ptr = capsule(builtins[id]);

Edit: Originally suggested internals &*, but edited back to internals **.

Py_Finalize could potentially invoke code that calls `get_internals()`,
which could create a new internals object if one didn't exist.
`finalize_interpreter()` didn't catch this because it only used the
pre-finalize interpreter pointer status; if this happens, it results in
the internals pointer not being properly destroyed with the interpreter,
which leaks, and also causes a `get_internals()` under a future
interpreter to return an internals object that is wrong in various ways.
@jagerman jagerman force-pushed the internals-destroy-fix branch from dfa4238 to 4238def Compare June 8, 2017 18:35
@jagerman jagerman merged commit 4edb1ce into pybind:master Jun 8, 2017
@dean0x7d dean0x7d modified the milestone: v2.2 Aug 13, 2017
@jagerman jagerman deleted the internals-destroy-fix branch August 14, 2017 20:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants