Skip to content

Free created types' tp_name in default metaclass #978

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
Aug 5, 2017

Conversation

jagerman
Copy link
Member

@jagerman jagerman commented Aug 3, 2017

Fixes #977, via a weakref added to the type.

This feels like a bit of overkill, though; the leak in #977 seems fairly minor.

@jagerman jagerman force-pushed the free-tp_name branch 2 times, most recently from ec0937c to a1fa350 Compare August 3, 2017 23:13
@aldanor
Copy link
Member

aldanor commented Aug 4, 2017

👍 Don't think it's an overkill, looks quite straightforward. Keeping the the codebase valgrind-clean is nice.

What about strdup() of docstrings, wonder if it should be done the same? (in initialize_generic(), IIRC)

@dean0x7d
Copy link
Member

dean0x7d commented Aug 4, 2017

Plugging the leak is definitely important, but the implementation with a weakref callback looks like total overkill to me. Why not use the metaclass' tp_dealloc?

@jagerman
Copy link
Member Author

jagerman commented Aug 4, 2017

I tried that, but at least with a simple approach it results in invalid frees because the metaclass's tp_dealloc gets called for Python-inherited types as well, where free()ing is definitely wrong.

@jagerman
Copy link
Member Author

jagerman commented Aug 4, 2017

Another way we could go about this is to store the type names in a std::forward_list<std::string> in internals. Then at least it'll be destroyed when the interpreter is finalized (which AFAICT is the only way a pybind-created type is going to be destroyed anyway).

@@ -484,6 +484,7 @@ struct internals {
std::forward_list<void (*) (std::exception_ptr)> registered_exception_translators;
std::unordered_map<std::string, void *> shared_data; // Custom data to be shared across extensions
std::vector<PyObject *> loader_patient_stack; // Used by `loader_life_support`
std::forward_list<std::string> type_names; // Stores the std::strings holding created types' tp_names
Copy link
Member

Choose a reason for hiding this comment

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

Minor: might as well name it static_strings or the like? (unlike all other fields of internals, this one you would never actually read, it's just there for storage with static lifetime and doesn't really have to do much with types)

Also, in case we ever need it again?

const char* detail::strdup(const std::string& what) {
    auto& internals = get_internals();
    internals.static_strings.emplace_front(what);
    return internals.static_strings.front().c_str();
}

Types need `tp_name` set to a C-style string, but the current `strdup`
ends up with a leak (issue pybind#977).  This avoids the strdup by storing
the `std::string` in internals so that during interpreter shutdown it
will be properly destroyed.
@aldanor
Copy link
Member

aldanor commented Aug 5, 2017

Looks great. Merge?

@jagerman jagerman merged commit 2640c95 into pybind:master Aug 5, 2017
@dean0x7d dean0x7d modified the milestone: v2.2 Aug 13, 2017
@jagerman jagerman deleted the free-tp_name branch August 14, 2017 20:25
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.

3 participants