Package: src:dm-tree
Version: 0.1.9-1
User: [email protected]
Usertags: python3.15
Tags: patch, ftbfs, forky, sid
Severity: important

Hi!

While rebuilding the python related packages against the Python 3.15rc2
version we found that dm-tree fails to build from source [1].

The error is:

pybind11::handle::dec_ref() is being called while the GIL is either not held or 
invalid. Please see 
https://pybind11.readthedocs.io/en/stable/advanced/misc.html#common-sources-of-global-interpreter-lock-errors
 for debugging advice.
    If you are convinced there is no bug in your code, you can #define 
PYBIND11_NO_ASSERT_GIL_HELD_INCREF_DECREF to disable this check. In that case 
you have to ensure this #define is consistently used for all translation units 
linked into a given pybind11 extension, otherwise there will be ODR violations. 
The failing pybind11::handle::dec_ref() call was triggered on a ABCMeta object.
    terminate called after throwing an instance of 'std::runtime_error'
      what():  pybind11::handle::dec_ref() PyGILState_Check() failure.
    Aborted
    E: pybuild pybuild:485: test: plugin pyproject failed with: exit code=134: 
cd /build/reproducible-path/dm-tree-0.1.9/.pybuild/cpython3_3.15_dm-tree/build; 
python3.15 -m pytest

To fix the issues I had to apply two fixes:
- Backport c9be91f8 Add support for python 3.14 [2]. Which was already
  included in version 0.1.10.
- Add patch to Release static Python objects to avoid dec_ref during
  finalization. This is because in Python 3.15 this triggers the
  PyGILState_Check() assertion.

I've applied these fixes in the sandbox [3] to verify that it builds
successfully, please consider applying the patch to support the upcoming
3.15 version.

Setting the severity to important for now. Once Python 3.15 is released,
it will be added to python3-defaults and this bug will become release
critical.

Happy hacking,

[1]: https://debusine.debian.net/debian/r-python-python3.15/artifact/4597612/
[2]: 
https://github.com/google-deepmind/tree/commit/c9be91f8a9b84435da0d1e25b1d4bb4e249bc612
[3]: https://debusine.debian.net/debian/r-python-python3.15/

--
"Can you imagine what I would do if I could do all I can?" -- Sun Tzu
Saludos /\/\ /\ >< `/
From: Mathieu Scheltienne <[email protected]>
Date: Thu, 26 Mar 2026 20:29:20 +0100
Subject: Add support for python 3.14

Origin: upstream, https://github.com/google-deepmind/tree/commit/c9be91f8a9b84435da0d1e25b1d4bb4e249bc612
---
 tree/tree.cc | 26 +++++++++++++++-----------
 1 file changed, 15 insertions(+), 11 deletions(-)

--- a/tree/tree.cc
+++ b/tree/tree.cc
@@ -15,12 +15,13 @@
 #include "tree.h"
 
 #include <functional>
+#include <atomic>
 #include <memory>
+#include <mutex>
 #include <string>
 #include <unordered_map>
 
 // logging
-#include "absl/memory/memory.h"
 #include "absl/strings/str_cat.h"
 #include "absl/strings/string_view.h"
 #include <pybind11/pybind11.h>
@@ -50,7 +51,7 @@
 
 const int kMaxItemsInCache = 1024;
 
-bool WarnedThatSetIsNotSequence = false;
+std::atomic<bool> WarnedThatSetIsNotSequence{false};
 
 bool IsString(PyObject* o) {
   return PyBytes_Check(o) || PyByteArray_Check(o) || PyUnicode_Check(o);
@@ -114,6 +115,7 @@
     auto* type = Py_TYPE(o);
 
     {
+      std::lock_guard<std::mutex> lock(mutex_);
       auto it = type_to_sequence_map_.find(type);
       if (it != type_to_sequence_map_.end()) {
         return it->second;
@@ -133,6 +135,7 @@
     // that are eligible for decref. As a precaution, we limit the size of the
     // map to 1024.
     {
+      std::lock_guard<std::mutex> lock(mutex_);
       if (type_to_sequence_map_.size() < kMaxItemsInCache) {
         Py_INCREF(type);
         type_to_sequence_map_.insert({type, check_result});
@@ -145,29 +148,30 @@
  private:
   std::function<int(PyObject*)> ternary_predicate_;
   std::unordered_map<PyTypeObject*, bool> type_to_sequence_map_;
+  mutable std::mutex mutex_;
 };
 
 py::object GetCollectionsSequenceType() {
   static py::object type =
-      py::module::import("collections.abc").attr("Sequence");
+      py::module_::import("collections.abc").attr("Sequence");
   return type;
 }
 
 py::object GetCollectionsMappingType() {
   static py::object type =
-      py::module::import("collections.abc").attr("Mapping");
+      py::module_::import("collections.abc").attr("Mapping");
   return type;
 }
 
 py::object GetCollectionsMappingViewType() {
   static py::object type =
-      py::module::import("collections.abc").attr("MappingView");
+      py::module_::import("collections.abc").attr("MappingView");
   return type;
 }
 
 py::object GetWraptObjectProxyTypeUncached() {
   try {
-    return py::module::import("wrapt").attr("ObjectProxy");
+    return py::module_::import("wrapt").attr("ObjectProxy");
   } catch (const py::error_already_set& e) {
     if (e.matches(PyExc_ImportError)) return py::none();
     throw e;
@@ -722,13 +726,13 @@
 
 ValueIteratorPtr GetValueIterator(PyObject* nested) {
   if (PyDict_Check(nested)) {
-    return absl::make_unique<DictValueIterator>(nested);
+    return std::make_unique<DictValueIterator>(nested);
   } else if (IsMappingHelper(nested)) {
-    return absl::make_unique<MappingValueIterator>(nested);
+    return std::make_unique<MappingValueIterator>(nested);
   } else if (IsAttrsHelper(nested)) {
-    return absl::make_unique<AttrsValueIterator>(nested);
+    return std::make_unique<AttrsValueIterator>(nested);
   } else {
-    return absl::make_unique<SequenceValueIterator>(nested);
+    return std::make_unique<SequenceValueIterator>(nested);
   }
 }
 
@@ -741,7 +745,7 @@
   return py::reinterpret_steal<py::object>(ptr);
 }
 
-PYBIND11_MODULE(_tree, m) {
+PYBIND11_MODULE(_tree, m, py::mod_gil_not_used()) {
   // Resolve `wrapt.ObjectProxy` at import time to avoid doing
   // imports during function calls.
   tree::GetWraptObjectProxyType();
From: Maximiliano Curia <[email protected]>
Date: Tue, 8 Sep 2026 10:48:00 +0200
Subject: Release static Python objects to avoid dec_ref during finalization.
---
 tree/tree.cc | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

Index: python-dm-tree/tree/tree.cc
===================================================================
--- python-dm-tree.orig/tree/tree.cc
+++ python-dm-tree/tree/tree.cc
@@ -151,21 +151,21 @@ class CachedTypeCheck {
   mutable std::mutex mutex_;
 };
 
-py::object GetCollectionsSequenceType() {
-  static py::object type =
-      py::module_::import("collections.abc").attr("Sequence");
+py::handle GetCollectionsSequenceType() {
+  static py::handle type =
+      py::object(py::module_::import("collections.abc").attr("Sequence")).release();
   return type;
 }
 
-py::object GetCollectionsMappingType() {
-  static py::object type =
-      py::module_::import("collections.abc").attr("Mapping");
+py::handle GetCollectionsMappingType() {
+  static py::handle type =
+      py::object(py::module_::import("collections.abc").attr("Mapping")).release();
   return type;
 }
 
-py::object GetCollectionsMappingViewType() {
-  static py::object type =
-      py::module_::import("collections.abc").attr("MappingView");
+py::handle GetCollectionsMappingViewType() {
+  static py::handle type =
+      py::object(py::module_::import("collections.abc").attr("MappingView")).release();
   return type;
 }
 

Reply via email to