Skip to content

[master] Wrong caching of overrides - #3465

Merged
Skylion007 merged 5 commits into
pybind:masterfrom
Trigve:override_cache_master
Nov 15, 2021
Merged

Skylion007 merged 5 commits into
pybind:masterfrom
Trigve:override_cache_master

Conversation

@Trigve

@Trigve Trigve commented Nov 13, 2021

Copy link
Copy Markdown
Contributor

Description

There was a problem when the python type, which was stored in override
cache for C++ functions, was destroyed and the record wasn't removed from the
override cache. Therefor, dangling pointer was stored there. Then when the
memory was reused and new type was allocated at the given address and the
method with the same name (as previously stored in the cache) was actually
overridden in python, it would wrongly find it in the override cache for C++
functions and therefor override from python wouldn't be called.
The fix is to erase the type from the override cache when the type is destroyed.

Closes: #3369

Suggested changelog entry:

Fix caching of the C++ overrides

There was a problem when the python type, which was stored in override
cache for C++ functions, was destroyed and  the record wasn't removed from the
override cache. Therefor, dangling pointer was stored there. Then when the
memory was reused and new type was allocated at the given address and the
method with the same name (as previously stored in the cache) was actually
overridden in python, it would wrongly find it in the override cache for C++
functions and therefor override from python wouldn't be called.
The fix is to erase the type from the override cache when the type is destroyed.
@rwgk

rwgk commented Nov 13, 2021

Copy link
Copy Markdown
Collaborator

FYI I'll be on and off a lot today but will keep an eye on this.

@rwgk rwgk left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggestions aiming to nudge things to the right places.

Comment thread include/pybind11/pybind11.h Outdated
weakref((PyObject *) type, cpp_function([type](handle wr) {
get_internals().registered_types_py.erase(type);

// Actually just `std::erase_if`, but that's only available in C++20

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

What do you think about something like:

erase_if(cache.begin(), cache.end(), [](const xxx& v){ return yyy; });

here and implementing erase_if in detail/common.h (bottom), using the "(2) equivalent to" code from here:

https://en.cppreference.com/w/cpp/container/vector/erase2

auto it = std::remove_if(c.begin(), c.end(), pred);
auto r = std::distance(it, c.end());
c.erase(it, c.end());
return r;

Later, when we introduce PYBIND11_CPP20 we can use std::erase_if directly. (Maybe just leave something like // TODO PYBIND11_CPP20: std::erase_if for now.)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The code for the erasure was actually copied and modified from

// Actually just `std::erase_if`, but that's only available in C++20

It would be better to create a helper function as you suggested, but I didn't want to add it in this PR as it isn't isn't connected to the issue. I think it would be better to add it as a separate commit.

Comment thread tests/test_class.cpp Outdated
test_derived(test_derived const &Copy) = delete;
};

class py_test_derived : public test_derived {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Personal preference for clarity (in case you like that, too): class test_derived_trampoline : test_derived

@Trigve Trigve Nov 13, 2021 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Renamed to test_override_cache_helper_trampoline

Comment thread tests/test_class.cpp Outdated
std::vector<int> vec;
};

class test_derived {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

At 2nd look, test_virtual_functions.* appears to be a significantly better fit, because this is closely tied to trampolines.

test_derived is a very generic name, something a bit more tailored to the purpose would be ideal (easier to pin-point and relate to what's being exerised). Maybe exercise_override_cache or test_override_cache_helper ...?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Moved and renamed to test_override_cache_helper

@@ -0,0 +1,18 @@
# -*- coding: utf-8 -*-

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Does test_trampoline make sense here? To leave it a little bit open (for the future) but not a widely as "derived".

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Renamed to test_trampoline.py

Rename the classes and files so they're no too generic. Also, better place to
test the stuff is in test_virtual_functions.cpp/.py as we're basically testing
the virtual functions/trampolines.
@rwgk

rwgk commented Nov 13, 2021 via email

Copy link
Copy Markdown
Collaborator

@Trigve

Trigve commented Nov 13, 2021

Copy link
Copy Markdown
Contributor Author

I cannot look at the code right now, but from the comments it sounds good. If you haven't done already, could you please add a comment here: todo consolidate with xxx in class.h? Also request review from Skylion007

How do I request a review? I've read the docs but I don't have option to add one.

@rwgk

rwgk commented Nov 13, 2021 via email

Copy link
Copy Markdown
Collaborator

@rwgk
rwgk requested a review from Skylion007 November 13, 2021 22:22
@rwgk

rwgk commented Nov 14, 2021

Copy link
Copy Markdown
Collaborator

@henryiii do you want to take a look, too?

@henryiii henryiii left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Looks reasonable to me.

@Skylion007
Skylion007 merged commit afdc09d into pybind:master Nov 15, 2021
@github-actions github-actions Bot added the needs changelog Possibly needs a changelog entry label Nov 15, 2021
@rwgk

rwgk commented Nov 15, 2021

Copy link
Copy Markdown
Collaborator

Thanks @Trigve for the great unit tests!

rwgk added a commit to rwgk/pybind11 that referenced this pull request Nov 15, 2021
@Trigve
Trigve deleted the override_cache_master branch November 16, 2021 15:07
@henryiii henryiii removed the needs changelog Possibly needs a changelog entry label Dec 21, 2021
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.

[BUG]: Wrong caching of the overrides

4 participants