Skip to content

Commit ac21545

Browse files
committed
Force hidden visibility on functions under gcc for distinct static locals
This commit adds an attribute macro PYBIND11_UNSHARED_STATIC_LOCALS that forces a function to have hidden visibility under gcc. This is needed to force gcc to avoid sharing static local instances across modules (which happens even under a RTLD_LOCAL dlopen()!) This updates the workaround from #862 to use this rather than the version-specific-template.
1 parent 56190b7 commit ac21545

File tree

2 files changed

+12
-9
lines changed

2 files changed

+12
-9
lines changed

include/pybind11/cast.h

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,7 @@ struct type_info {
6060
bool default_holder : 1;
6161
};
6262

63-
// Store the static internals pointer in a version-specific function so that we're guaranteed it
64-
// will be distinct for modules compiled for different pybind11 versions. Without this, some
65-
// compilers (i.e. gcc) can use the same static pointer storage location across different .so's,
66-
// even though the `get_internals()` function itself is local to each shared object.
67-
template <int = PYBIND11_VERSION_MAJOR, int = PYBIND11_VERSION_MINOR>
68-
internals *&get_internals_ptr() { static internals *internals_ptr = nullptr; return internals_ptr; }
63+
PYBIND11_UNSHARED_STATIC_LOCALS internals *&get_internals_ptr() { static internals *internals_ptr = nullptr; return internals_ptr; }
6964

7065
PYBIND11_NOINLINE inline internals &get_internals() {
7166
internals *&internals_ptr = get_internals_ptr();
@@ -128,13 +123,11 @@ PYBIND11_NOINLINE inline internals &get_internals() {
128123
return *internals_ptr;
129124
}
130125

131-
namespace {
132126
// Works like internals.registered_types_cpp, but for module-local registered types:
133-
inline type_map<void *> &registered_local_types_cpp() {
127+
PYBIND11_NOINLINE PYBIND11_UNSHARED_STATIC_LOCALS inline type_map<void *> &registered_local_types_cpp() {
134128
static type_map<void *> locals{};
135129
return locals;
136130
}
137-
}
138131

139132
/// A life support system for temporary objects created by `type_caster::load()`.
140133
/// Adding a patient will keep it alive up until the enclosing function returns.

include/pybind11/common.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,16 @@
6868
# endif
6969
#endif
7070

71+
// Attribute macro for a function containing one or more static local variables that mustn't share
72+
// the variable across shared objects (for example, because the value might be incompatible for
73+
// modules compiled under different pybind versions). This currently only has an effect under g++,
74+
// which forces the function visibility to "hidden" which avoids the sharing.
75+
#if defined(__GNUG__) && !defined(__clang__)
76+
# define PYBIND11_UNSHARED_STATIC_LOCALS __attribute__ ((visibility("hidden")))
77+
#else
78+
# define PYBIND11_UNSHARED_STATIC_LOCALS
79+
#endif
80+
7181
#if defined(_MSC_VER)
7282
# define PYBIND11_NOINLINE __declspec(noinline)
7383
#else

0 commit comments

Comments
 (0)