-
Notifications
You must be signed in to change notification settings - Fork 2.1k
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
smart_holder trampoline shared_from_this support #3023
Merged
Merged
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Closing/Opening to work around flake (see #2995). |
This was referenced Jun 15, 2021
Merged
37dbb55
to
36299d1
Compare
rwgk
added a commit
to rwgk/rwgk_tbx
that referenced
this pull request
Jun 24, 2021
…/pybind11#3023 with commit 316d375fba5485c67fc76bd48bbd73c53c9360ff.
5918b2e
to
066edb0
Compare
…der in test_class_sh_shared_from_this.cpp
…tests. Skipping the only test that generates an ASAN heap-use-after-free.
…riginal tests/test_smart_ptr.py.
…tic_assert that also triggers for derived classes.
…_this also for unowned pointees.
…hared_from_this mechanism.
…f `pointee_depends_on_holder_owner`, but currently only for `from_raw_ptr_take_ownership`.
…t to exercise the path through `cast`. The path through init.h is missing a test that would fail if the flag is incorrect. The plan is to systematically cover all situations (there are many that are not exercised for shared_from_this).
…oad issue affecting all MSVC builds.
…HA download issue affecting all MSVC builds." This reverts commit f4e1112. It didn't help.
https://github.com/deepmind/open_spiel/tree/bbfb0259b5d26c1e3f05000f1f4a05b7ad60393e/open_spiel/python/mfg/algorithms best_response_value_test distribution_test fictitious_play_test greedy_policy_test nash_conv_test policy_value_test CAVEAT: The fix is NOT covered by pybind11 unit tests.
Completes unit test coverage for the changed code in smart_holder_type_casters.h.
…le changes in smart_holder_type_caster_load, trying to work on weak_ptr for shared_ptr_trampoline_self_life_support, but that didn't work out. Manually fully leak-checked again.
066edb0
to
45fbdfc
Compare
Merging comment:
|
It would be good if the description of the various subtle pieces involved with using enable_shared_from_this were put into the README. |
OpenSpiel
pushed a commit
to google-deepmind/open_spiel
that referenced
this pull request
Aug 21, 2022
…ython games. The pybind smart_holder logic will create a shared_ptr for Python-created objects only when required to do so. This means that if a Python-implemented game is passed from Python to C++ as Game& and then a C++ function calls shared_from_this() on it, this will fail unless there's already a C++ shared_ptr for some other reason. The fix is either: a - Amend the C++ interface to take shared_ptr instead of refs b - Introduce a lambda function in the pybind interface, taking a shared_ptr and dereferencing it to call the ref-based C++ implementation Either option will result in pybind creating a shared_ptr for us before calling our C++ code. To minimize disruption to existing code, and forestall future failures, I've applied change (b) everywhere I could see, even though not every case was failing (because not every case called shared_from_this in the C++ implementation). For further details of the relevant pybind internals, see pybind/pybind11#3023 fixes: #905 PiperOrigin-RevId: 469016236 Change-Id: I9467eeb992f3463a432cc7060c46404d2bbd4638
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Before this PR the
smart_holder
type_caster
implementation did not takestd::enable_shared_from_this into
account at all. As long as no trampolines are involved, that was fine, but the "inheritance slicing" issue (#1333) resurfacesshared_from_this
uses its supportingweak_ptr
as a backdoor to theshared_ptr
insidesmart_holder
,gc
.Unfortunately the approach pioneered under PR #2839, and adopted in the
smart_holder
code, does not play nicely withshared_from_this
. Here it gets complicated:shared_from_this
behavior was not even fully defined for a situation in which multipleshared_ptr
objects exist simultaneously (which is valid if custom deleters are involved, and exactly what thesmart_holder
code does).shared_from_this
will retrieve the first shared_ptr object created (until it expires):std::shared_ptr
to the internally stored weak reference [if not already owned by a livestd::shared_ptr
(since C++17)]"How can this be made to play nicely with pybind11 trampolines?
Omitting a very long story of failed experiments in the commit history of this PR, the key trick is:
shared_ptr
insidesmart_holder
invisible to theshared_from_this
mechanism, by casting the raw pointer tovoid *
before passing it to theshared_ptr
constructor (orshared_ptr::reset
, to be precise wrt to thesmart_holder
implementation).With that, the PR #2839 approach works again, although it also introduces a subtle but important requirement:
shared_from_this
will only succeed (vs throwing abad_weak_ptr
exception) while C++ code, outside of thesmart_holder
, owns ashared_ptr
object.That means, a situation that boils down to the following can (if no other non-
smart_holder
shared_ptr
exists at call time) trigger abad_weak_ptr
RuntimeError
:An obvious way to solve the problem is to redefine
foo()
:But if that's not an option (e.g. because it is an external dependency that cannot easily be modified), there is an easy alternative trick:
The lambda function keeps the
shared_ptr
alive for the duration of thefoo()
function call. Problem solved.This PR goes one step further, although that's mostly a nicety. The
smart_holder
now also keeps aweak_ptr
to theshared_ptr
that keeps the trampoline Python object alive, and uses theweak_ptr
to generateshared_ptr
objects in repeated calls. Therefore theuse_count
s of the returnedshared_ptr
objects are in line with naive expectations.It is possible that this PR does not solve all possible corner cases of
shared_from_this
interacting with thesmart_holder
implementation, but at least it goes from "clearly incorrect behavior" to "mostly correct". Systematic test coverage for all corner cases, with fixes if any, is very involved and will be done separately.