aboutsummaryrefslogtreecommitdiffstats
path: root/3rdparty/pybind11/tests/cross_module_interleaved_error_already_set.cpp
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/pybind11/tests/cross_module_interleaved_error_already_set.cpp')
-rw-r--r--3rdparty/pybind11/tests/cross_module_interleaved_error_already_set.cpp51
1 files changed, 51 insertions, 0 deletions
diff --git a/3rdparty/pybind11/tests/cross_module_interleaved_error_already_set.cpp b/3rdparty/pybind11/tests/cross_module_interleaved_error_already_set.cpp
new file mode 100644
index 00000000..fdd9939e
--- /dev/null
+++ b/3rdparty/pybind11/tests/cross_module_interleaved_error_already_set.cpp
@@ -0,0 +1,51 @@
+/*
+ Copyright (c) 2022 Google LLC
+
+ All rights reserved. Use of this source code is governed by a
+ BSD-style license that can be found in the LICENSE file.
+*/
+
+#include <pybind11/pybind11.h>
+
+// This file mimics a DSO that makes pybind11 calls but does not define a PYBIND11_MODULE,
+// so that the first call of cross_module_error_already_set() triggers the first call of
+// pybind11::detail::get_internals().
+
+namespace {
+
+namespace py = pybind11;
+
+void interleaved_error_already_set() {
+ PyErr_SetString(PyExc_RuntimeError, "1st error.");
+ try {
+ throw py::error_already_set();
+ } catch (const py::error_already_set &) {
+ // The 2nd error could be conditional in a real application.
+ PyErr_SetString(PyExc_RuntimeError, "2nd error.");
+ } // Here the 1st error is destroyed before the 2nd error is fetched.
+ // The error_already_set dtor triggers a pybind11::detail::get_internals()
+ // call via pybind11::gil_scoped_acquire.
+ if (PyErr_Occurred()) {
+ throw py::error_already_set();
+ }
+}
+
+constexpr char kModuleName[] = "cross_module_interleaved_error_already_set";
+
+struct PyModuleDef moduledef = {
+ PyModuleDef_HEAD_INIT, kModuleName, nullptr, 0, nullptr, nullptr, nullptr, nullptr, nullptr};
+
+} // namespace
+
+extern "C" PYBIND11_EXPORT PyObject *PyInit_cross_module_interleaved_error_already_set() {
+ PyObject *m = PyModule_Create(&moduledef);
+ if (m != nullptr) {
+ static_assert(sizeof(&interleaved_error_already_set) == sizeof(void *),
+ "Function pointer must have the same size as void *");
+ PyModule_AddObject(
+ m,
+ "funcaddr",
+ PyLong_FromVoidPtr(reinterpret_cast<void *>(&interleaved_error_already_set)));
+ }
+ return m;
+}