Skip to content

Commit 0131c55

Browse files
committed
Merge branch 'master' into incompat
2 parents 1d2f952 + f7e14e9 commit 0131c55

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+741
-86
lines changed

.github/workflows/ci.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ jobs:
3939
- 'pypy-3.8'
4040
- 'pypy-3.9'
4141
- 'pypy-3.10'
42+
- 'graalpy-24.1'
4243

4344
# Items in here will either be added to the build matrix (if not
4445
# present), or add new keys to an existing matrix element if all the
@@ -85,6 +86,10 @@ jobs:
8586
# Extra ubuntu latest job
8687
- runs-on: ubuntu-latest
8788
python: '3.11'
89+
exclude:
90+
# The setup-python action currently doesn't have graalpy for windows
91+
- python: 'graalpy-24.1'
92+
runs-on: 'windows-2022'
8893

8994

9095
name: "🐍 ${{ matrix.python }} • ${{ matrix.runs-on }} • x64 ${{ matrix.args }}"

docs/advanced/deadlock.md

Lines changed: 391 additions & 0 deletions
Large diffs are not rendered by default.

docs/advanced/misc.rst

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,11 @@ will acquire the GIL before calling the Python callback. Similarly, the
6262
back into Python.
6363

6464
When writing C++ code that is called from other C++ code, if that code accesses
65-
Python state, it must explicitly acquire and release the GIL.
65+
Python state, it must explicitly acquire and release the GIL. A separate
66+
document on deadlocks [#f8]_ elaborates on a particularly subtle interaction
67+
with C++'s block-scope static variable initializer guard mutexes.
68+
69+
.. [#f8] See docs/advanced/deadlock.md
6670
6771
The classes :class:`gil_scoped_release` and :class:`gil_scoped_acquire` can be
6872
used to acquire and release the global interpreter lock in the body of a C++
@@ -142,6 +146,9 @@ following checklist.
142146
destructors can sometimes get invoked in weird and unexpected circumstances as a result
143147
of exceptions.
144148

149+
- C++ static block-scope variable initialization that calls back into Python can
150+
cause deadlocks; see [#f8]_ for a detailed discussion.
151+
145152
- You should try running your code in a debug build. That will enable additional assertions
146153
within pybind11 that will throw exceptions on certain GIL handling errors
147154
(reference counting operations).

include/pybind11/cast.h

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,7 @@ class type_caster<bool> {
343343
#else
344344
// Alternate approach for CPython: this does the same as the above, but optimized
345345
// using the CPython API so as to avoid an unneeded attribute lookup.
346-
else if (auto *tp_as_number = src.ptr()->ob_type->tp_as_number) {
346+
else if (auto *tp_as_number = Py_TYPE(src.ptr())->tp_as_number) {
347347
if (PYBIND11_NB_BOOL(tp_as_number)) {
348348
res = (*PYBIND11_NB_BOOL(tp_as_number))(src.ptr());
349349
}
@@ -1564,15 +1564,24 @@ struct function_call {
15641564
handle init_self;
15651565
};
15661566

1567+
// See PR #5396 for the discussion that led to this
1568+
template <typename Base, typename Derived, typename = void>
1569+
struct is_same_or_base_of : std::is_same<Base, Derived> {};
1570+
1571+
// Only evaluate is_base_of if Derived is complete.
1572+
// is_base_of raises a compiler error if Derived is incomplete.
1573+
template <typename Base, typename Derived>
1574+
struct is_same_or_base_of<Base, Derived, decltype(void(sizeof(Derived)))>
1575+
: any_of<std::is_same<Base, Derived>, std::is_base_of<Base, Derived>> {};
1576+
15671577
/// Helper class which loads arguments for C++ functions called from Python
15681578
template <typename... Args>
15691579
class argument_loader {
15701580
using indices = make_index_sequence<sizeof...(Args)>;
1571-
15721581
template <typename Arg>
1573-
using argument_is_args = std::is_base_of<args, intrinsic_t<Arg>>;
1582+
using argument_is_args = is_same_or_base_of<args, intrinsic_t<Arg>>;
15741583
template <typename Arg>
1575-
using argument_is_kwargs = std::is_base_of<kwargs, intrinsic_t<Arg>>;
1584+
using argument_is_kwargs = is_same_or_base_of<kwargs, intrinsic_t<Arg>>;
15761585
// Get kwargs argument position, or -1 if not present:
15771586
static constexpr auto kwargs_pos = constexpr_last<argument_is_kwargs, Args...>();
15781587

include/pybind11/detail/common.h

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -164,14 +164,6 @@
164164
# endif
165165
#endif
166166

167-
#if !defined(PYBIND11_EXPORT_EXCEPTION)
168-
# if defined(__apple_build_version__)
169-
# define PYBIND11_EXPORT_EXCEPTION PYBIND11_EXPORT
170-
# else
171-
# define PYBIND11_EXPORT_EXCEPTION
172-
# endif
173-
#endif
174-
175167
// For CUDA, GCC7, GCC8:
176168
// PYBIND11_NOINLINE_FORCED is incompatible with `-Wattributes -Werror`.
177169
// When defining PYBIND11_NOINLINE_FORCED, it is best to also use `-Wno-attributes`.
@@ -299,7 +291,7 @@ PYBIND11_WARNING_DISABLE_MSVC(4505)
299291
# define PYBIND11_INTERNAL_NUMPY_1_ONLY_DETECTED
300292
#endif
301293

302-
#if defined(PYPY_VERSION) && !defined(PYBIND11_SIMPLE_GIL_MANAGEMENT)
294+
#if (defined(PYPY_VERSION) || defined(GRAALVM_PYTHON)) && !defined(PYBIND11_SIMPLE_GIL_MANAGEMENT)
303295
# define PYBIND11_SIMPLE_GIL_MANAGEMENT
304296
#endif
305297

@@ -329,6 +321,17 @@ PYBIND11_WARNING_POP
329321
# endif
330322
#endif
331323

324+
// For libc++, the exceptions should be exported,
325+
// otherwise, the exception translation would be incorrect.
326+
// IMPORTANT: This code block must stay BELOW the #include <exception> above (see PR #5390).
327+
#if !defined(PYBIND11_EXPORT_EXCEPTION)
328+
# if defined(_LIBCPP_EXCEPTION)
329+
# define PYBIND11_EXPORT_EXCEPTION PYBIND11_EXPORT
330+
# else
331+
# define PYBIND11_EXPORT_EXCEPTION
332+
# endif
333+
#endif
334+
332335
// Must be after including <version> or one of the other headers specified by the standard
333336
#if defined(__cpp_lib_char8_t) && __cpp_lib_char8_t >= 201811L
334337
# define PYBIND11_HAS_U8STRING
@@ -387,6 +390,20 @@ PYBIND11_WARNING_POP
387390
#define PYBIND11_CONCAT(first, second) first##second
388391
#define PYBIND11_ENSURE_INTERNALS_READY pybind11::detail::get_internals();
389392

393+
#if !defined(GRAALVM_PYTHON)
394+
# define PYBIND11_PYCFUNCTION_GET_DOC(func) ((func)->m_ml->ml_doc)
395+
# define PYBIND11_PYCFUNCTION_SET_DOC(func, doc) \
396+
do { \
397+
(func)->m_ml->ml_doc = (doc); \
398+
} while (0)
399+
#else
400+
# define PYBIND11_PYCFUNCTION_GET_DOC(func) (GraalPyCFunction_GetDoc((PyObject *) (func)))
401+
# define PYBIND11_PYCFUNCTION_SET_DOC(func, doc) \
402+
do { \
403+
GraalPyCFunction_SetDoc((PyObject *) (func), (doc)); \
404+
} while (0)
405+
#endif
406+
390407
#define PYBIND11_CHECK_PYTHON_VERSION \
391408
{ \
392409
const char *compiled_ver \

include/pybind11/detail/internals.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -460,7 +460,7 @@ inline void translate_local_exception(std::exception_ptr p) {
460460

461461
inline object get_python_state_dict() {
462462
object state_dict;
463-
#if PYBIND11_INTERNALS_VERSION <= 4 || defined(PYPY_VERSION)
463+
#if PYBIND11_INTERNALS_VERSION <= 4 || defined(PYPY_VERSION) || defined(GRAALVM_PYTHON)
464464
state_dict = reinterpret_borrow<object>(PyEval_GetBuiltins());
465465
#else
466466
# if PY_VERSION_HEX < 0x03090000
@@ -733,7 +733,8 @@ const char *c_str(Args &&...args) {
733733
}
734734

735735
inline const char *get_function_record_capsule_name() {
736-
#if PYBIND11_INTERNALS_VERSION > 4
736+
// On GraalPy, pointer equality of the names is currently not guaranteed
737+
#if PYBIND11_INTERNALS_VERSION > 4 && !defined(GRAALVM_PYTHON)
737738
return get_internals().function_record_capsule_name.c_str();
738739
#else
739740
return nullptr;

include/pybind11/detail/type_caster_base.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,7 @@ PYBIND11_NOINLINE handle get_object_handle(const void *ptr, const detail::type_i
459459
}
460460

461461
inline PyThreadState *get_thread_state_unchecked() {
462-
#if defined(PYPY_VERSION)
462+
#if defined(PYPY_VERSION) || defined(GRAALVM_PYTHON)
463463
return PyThreadState_GET();
464464
#elif PY_VERSION_HEX < 0x030D0000
465465
return _PyThreadState_UncheckedGet();

include/pybind11/eval.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,18 +94,18 @@ void exec(const char (&s)[N], object global = globals(), object local = object()
9494
eval<eval_statements>(s, std::move(global), std::move(local));
9595
}
9696

97-
#if defined(PYPY_VERSION)
97+
#if defined(PYPY_VERSION) || defined(GRAALVM_PYTHON)
9898
template <eval_mode mode = eval_statements>
9999
object eval_file(str, object, object) {
100-
pybind11_fail("eval_file not supported in PyPy3. Use eval");
100+
pybind11_fail("eval_file not supported in this interpreter. Use eval");
101101
}
102102
template <eval_mode mode = eval_statements>
103103
object eval_file(str, object) {
104-
pybind11_fail("eval_file not supported in PyPy3. Use eval");
104+
pybind11_fail("eval_file not supported in this interpreter. Use eval");
105105
}
106106
template <eval_mode mode = eval_statements>
107107
object eval_file(str) {
108-
pybind11_fail("eval_file not supported in PyPy3. Use eval");
108+
pybind11_fail("eval_file not supported in this interpreter. Use eval");
109109
}
110110
#else
111111
template <eval_mode mode = eval_statements>

include/pybind11/gil_safe_call_once.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
4646
// get processed only when it is the main thread's turn again and it is running
4747
// normal Python code. However, this will be unnoticeable for quick call-once
4848
// functions, which is usually the case.
49+
//
50+
// For in-depth background, see docs/advanced/deadlock.md
4951
template <typename T>
5052
class gil_safe_call_once_and_store {
5153
public:

include/pybind11/pybind11.h

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -573,8 +573,7 @@ class cpp_function : public function {
573573
// chain.
574574
chain_start = rec;
575575
rec->next = chain;
576-
auto rec_capsule
577-
= reinterpret_borrow<capsule>(((PyCFunctionObject *) m_ptr)->m_self);
576+
auto rec_capsule = reinterpret_borrow<capsule>(PyCFunction_GET_SELF(m_ptr));
578577
rec_capsule.set_pointer(unique_rec.release());
579578
guarded_strdup.release();
580579
} else {
@@ -634,12 +633,11 @@ class cpp_function : public function {
634633
}
635634
}
636635

637-
/* Install docstring */
638636
auto *func = (PyCFunctionObject *) m_ptr;
639-
std::free(const_cast<char *>(func->m_ml->ml_doc));
640637
// Install docstring if it's non-empty (when at least one option is enabled)
641-
func->m_ml->ml_doc
642-
= signatures.empty() ? nullptr : PYBIND11_COMPAT_STRDUP(signatures.c_str());
638+
auto *doc = signatures.empty() ? nullptr : PYBIND11_COMPAT_STRDUP(signatures.c_str());
639+
std::free(const_cast<char *>(PYBIND11_PYCFUNCTION_GET_DOC(func)));
640+
PYBIND11_PYCFUNCTION_SET_DOC(func, doc);
643641

644642
if (rec->is_method) {
645643
m_ptr = PYBIND11_INSTANCE_METHOD_NEW(m_ptr, rec->scope.ptr());
@@ -2780,8 +2778,8 @@ get_type_override(const void *this_ptr, const type_info *this_type, const char *
27802778
}
27812779

27822780
/* Don't call dispatch code if invoked from overridden function.
2783-
Unfortunately this doesn't work on PyPy. */
2784-
#if !defined(PYPY_VERSION)
2781+
Unfortunately this doesn't work on PyPy and GraalPy. */
2782+
#if !defined(PYPY_VERSION) && !defined(GRAALVM_PYTHON)
27852783
# if PY_VERSION_HEX >= 0x03090000
27862784
PyFrameObject *frame = PyThreadState_GetFrame(PyThreadState_Get());
27872785
if (frame != nullptr) {

0 commit comments

Comments
 (0)