mirror of
https://github.com/pybind/pybind11.git
synced 2026-03-14 20:27:47 +00:00
* Revert PR #5700 production code change (pybind11/detail/struct_smart_holder.h). ``` git checkout b19489145b2c7a117138632d624809dfb3b380bb~1 include/pybind11/detail/struct_smart_holder.h ``` * Introduce `get_internals().get_memory_guarded_delete()` * [skip ci] Only pass around `memory::get_guarded_delete` function pointer. * [skip ci] Change a variable name for internal consistency. Add 3 x NOTE: PYBIND11_INTERNALS_VERSION needs to be bumped if changes are made to this struct. * Add comment: get_internals().get_memory_guarded_delete does not need with_internals() * Traverse all DSOs to find memory::guarded_delete with matching RTTI. * Add nullptr check to dynamic_cast overload. Suggested by ChatGPT for these reasons: * Prevents runtime RTTI lookups on nullptr. * Helps avoid undefined behavior if users pass in nulls from failed casts or optional paths. * Ensures consistent return value semantics and no accidental access to vtable. * Improve smart_holder unique_ptr deleter compatibility checks across DSOs: * Replace RTTI-based detection of std::default_delete<T> with a constexpr check to avoid RTTI reliance * Add type_info_equal_across_dso_boundaries() fallback using type_info::name() for RTTI equality across macOS DSOs * Rename related flags and functions for clarity (e.g., builtin → std_default) * Improves ABI robustness and clarity of ownership checks in smart_holder * Trivial renaming for internal consistency: builtin_delete → std_default_delete * Add get_trampoline_self_life_support to detail::type_info (passes local testing). * Polish previous commit slightly. * [skip ci] Store memory::get_guarded_delete in `detail::type_info` instead of `detail::internals` (no searching across DSOs required). * Revert change suggested by ChatGPT. After double-checking, ChatGPT agrees this isn't needed. * Minor polishing.
66 lines
2.6 KiB
C
66 lines
2.6 KiB
C
// Copyright (c) 2021 The Pybind Development Team.
|
|
// All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
#pragma once
|
|
|
|
#include "detail/common.h"
|
|
#include "detail/using_smart_holder.h"
|
|
#include "detail/value_and_holder.h"
|
|
|
|
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
|
|
|
PYBIND11_NAMESPACE_BEGIN(detail)
|
|
// PYBIND11:REMINDER: Needs refactoring of existing pybind11 code.
|
|
inline bool deregister_instance(instance *self, void *valptr, const type_info *tinfo);
|
|
PYBIND11_NAMESPACE_END(detail)
|
|
|
|
// The original core idea for this struct goes back to PyCLIF:
|
|
// https://github.com/google/clif/blob/07f95d7e69dca2fcf7022978a55ef3acff506c19/clif/python/runtime.cc#L37
|
|
// URL provided here mainly to give proper credit.
|
|
struct trampoline_self_life_support {
|
|
// NOTE: PYBIND11_INTERNALS_VERSION needs to be bumped if changes are made to this struct.
|
|
detail::value_and_holder v_h;
|
|
|
|
trampoline_self_life_support() = default;
|
|
|
|
void activate_life_support(const detail::value_and_holder &v_h_) {
|
|
Py_INCREF((PyObject *) v_h_.inst);
|
|
v_h = v_h_;
|
|
}
|
|
|
|
void deactivate_life_support() {
|
|
Py_DECREF((PyObject *) v_h.inst);
|
|
v_h = detail::value_and_holder();
|
|
}
|
|
|
|
~trampoline_self_life_support() {
|
|
if (v_h.inst != nullptr && v_h.vh != nullptr) {
|
|
void *value_void_ptr = v_h.value_ptr();
|
|
if (value_void_ptr != nullptr) {
|
|
PyGILState_STATE threadstate = PyGILState_Ensure();
|
|
v_h.value_ptr() = nullptr;
|
|
v_h.holder<smart_holder>().release_disowned();
|
|
detail::deregister_instance(v_h.inst, value_void_ptr, v_h.type);
|
|
Py_DECREF((PyObject *) v_h.inst); // Must be after deregister.
|
|
PyGILState_Release(threadstate);
|
|
}
|
|
}
|
|
}
|
|
|
|
// For the next two, the default implementations generate undefined behavior (ASAN failures
|
|
// manually verified). The reason is that v_h needs to be kept default-initialized.
|
|
trampoline_self_life_support(const trampoline_self_life_support &) {}
|
|
trampoline_self_life_support(trampoline_self_life_support &&) noexcept {}
|
|
|
|
// These should never be needed (please provide test cases if you think they are).
|
|
trampoline_self_life_support &operator=(const trampoline_self_life_support &) = delete;
|
|
trampoline_self_life_support &operator=(trampoline_self_life_support &&) = delete;
|
|
};
|
|
|
|
PYBIND11_NAMESPACE_BEGIN(detail)
|
|
using get_trampoline_self_life_support_fn = trampoline_self_life_support *(*) (void *);
|
|
PYBIND11_NAMESPACE_END(detail)
|
|
|
|
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
|