--- Begin Message ---
Package: src:dbus-python
Version: 1.4.0-1
User: [email protected]
Usertags: python3.15
Hi!
While rebuilding packages against Python 3.15 we found that dbus-python
failed to build from source due to failing tests. All the tests were
saying something like:
test: dbus-python:standalone
start time: 10:20:31
duration: 0.05s
result: exit status 1
command:
DBUS_TEST_TMPDIR=/build/reproducible-path/dbus-python-1.4.0/build-3.15/test
DBUS_TOP_SRCDIR=/build/reproducible-path/dbus-python-1.4.0
DBUS_PYTHON_VERSION=1.4.0 MALLOC_PERTURB_=171
UBSAN_OPTIONS=halt_on_error=1:abort_on_error=1:print_summary=1:print_stacktrace=1
PYTHONPATH=/build/reproducible-path/dbus-python-1.4.0:/build/reproducible-path/dbus-python-1.4.0/test:/build/reproducible-path/dbus-python-1.4.0/build-3.15:/build/reproducible-path/dbus-python-1.4.0/build-3.15/test
MSAN_OPTIONS=halt_on_error=1:abort_on_error=1:print_summary=1:print_stacktrace=1
ASAN_OPTIONS=halt_on_error=1:abort_on_error=1:print_summary=1
DBUS_TEST_UNINSTALLED=1 DBUS_FATAL_WARNINGS=1 MESON_TEST_ITERATION=1
DBUS_TOP_BUILDDIR=/build/reproducible-path/dbus-python-1.4.0/build-3.15
/usr/bin/dbus-run-session --config-file
/build/reproducible-path/dbus-python-1.4.0/build-3.15/test/tmp-session-bus.conf
-- /usr/bin/python3.15
/build/reproducible-path/dbus-python-1.4.0/build-3.15/../test/test-standalone.py
----------------------------------- stderr -----------------------------------
Traceback (most recent call last):
File
"/build/reproducible-path/dbus-python-1.4.0/build-3.15/../test/test-standalone.py",
line 39, in <module>
import _dbus_bindings
SystemError: type _dbus_bindings.Connection has the Py_TPFLAGS_MANAGED_WEAKREF
flag but not Py_TPFLAGS_HAVE_GC flag
The problem seems to be caused by the fact that the Connection is a
GenericAlloc that's missing the PyGC_Head header header, this is now detected in
Python 3.15 (see: https://github.com/python/cpython/issues/134786).
The weakref was introduced by ebecd174 but the previous mechanism still
works, so I'm reverting ebecd174 and adding a regression test that
should fail in python 3.12 to 3.14.
Happy hacking,
--
"Backtracking algorithms are nondeterministic, not in the sense of being
random, but in the sense of having free will."
-- Robert W. Floyd
Saludos /\/\ /\ >< `/
From: Maximiliano Curia <[email protected]>
Date: Sat, 16 Aug 2026 12:00:00 +0200
Subject: Don't use Py_TPFLAGS_MANAGED_WEAKREF on types without
Py_TPFLAGS_HAVE_GC
Revert ebecd174 plus regression test.
Forwarded: no
Last-Update: 2026-08-16
---
Index: dbus-python/dbus_bindings/conn-internal.h
===================================================================
--- dbus-python.orig/dbus_bindings/conn-internal.h
+++ dbus-python/dbus_bindings/conn-internal.h
@@ -42,10 +42,8 @@ typedef struct {
*/
PyObject *object_paths;
-#if !DBUSPY_PY_VERSION_AT_LEAST(3, 12, 0, 0)
/* Weak-references list to make Connections weakly referenceable */
PyObject *weaklist;
-#endif
dbus_bool_t has_mainloop;
} Connection;
Index: dbus-python/dbus_bindings/conn.c
===================================================================
--- dbus-python.orig/dbus_bindings/conn.c
+++ dbus-python/dbus_bindings/conn.c
@@ -238,9 +238,7 @@ DBusPyConnection_NewConsumingDBusConnect
self->has_mainloop = (mainloop != Py_None);
self->conn = NULL;
self->filters = PyList_New(0);
-#if !DBUSPY_PY_VERSION_AT_LEAST(3, 12, 0, 0)
self->weaklist = NULL;
-#endif
if (!self->filters) goto err;
self->object_paths = PyDict_New();
if (!self->object_paths) goto err;
@@ -394,10 +392,7 @@ static void Connection_tp_dealloc(Connec
/* avoid clobbering any pending exception */
PyErr_Fetch(&et, &ev, &etb);
-#if !DBUSPY_PY_VERSION_AT_LEAST(3, 12, 0, 0)
- if (self->weaklist)
-#endif
- {
+ if (self->weaklist) {
PyObject_ClearWeakRefs((PyObject *)self);
}
@@ -460,19 +455,12 @@ PyTypeObject DBusPyConnection_Type = {
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
-#if DBUSPY_PY_VERSION_AT_LEAST(3, 12, 0, 0)
- Py_TPFLAGS_MANAGED_WEAKREF |
-#endif
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
Connection_tp_doc, /*tp_doc*/
0, /*tp_traverse*/
0, /*tp_clear*/
0, /*tp_richcompare*/
-#if DBUSPY_PY_VERSION_AT_LEAST(3, 12, 0, 0)
- 0, /*tp_weaklistoffset*/
-#else
offsetof(Connection, weaklist), /*tp_weaklistoffset*/
-#endif
0, /*tp_iter*/
0, /*tp_iternext*/
DBusPyConnection_tp_methods, /*tp_methods*/
Index: dbus-python/dbus_bindings/server.c
===================================================================
--- dbus-python.orig/dbus_bindings/server.c
+++ dbus-python/dbus_bindings/server.c
@@ -38,10 +38,8 @@ typedef struct {
/* The Connection subtype for which this Server is a factory */
PyObject *conn_class;
-#if !DBUSPY_PY_VERSION_AT_LEAST(3, 12, 0, 0)
/* Weak-references list to make server weakly referenceable */
PyObject *weaklist;
-#endif
PyObject *mainloop;
} Server;
@@ -425,9 +423,7 @@ Server_tp_new(PyTypeObject *cls, PyObjec
return NULL;
}
-#if !DBUSPY_PY_VERSION_AT_LEAST(3, 12, 0, 0)
((Server *)self)->weaklist = NULL;
-#endif
TRACE(self);
return self;
@@ -442,10 +438,7 @@ static void Server_tp_dealloc(Server *se
/* avoid clobbering any pending exception */
PyErr_Fetch(&et, &ev, &etb);
-#if !DBUSPY_PY_VERSION_AT_LEAST(3, 12, 0, 0)
- if (self->weaklist)
-#endif
- {
+ if (self->weaklist) {
PyObject_ClearWeakRefs((PyObject *)self);
}
@@ -577,19 +570,12 @@ PyTypeObject DBusPyServer_Type = {
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
-#if DBUSPY_PY_VERSION_AT_LEAST(3, 12, 0, 0)
- Py_TPFLAGS_MANAGED_WEAKREF |
-#endif
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
Server_tp_doc, /*tp_doc*/
0, /*tp_traverse*/
0, /*tp_clear*/
0, /*tp_richcompare*/
-#if DBUSPY_PY_VERSION_AT_LEAST(3, 12, 0, 0)
- 0, /*tp_weaklistoffset*/
-#else
offsetof(Server, weaklist), /*tp_weaklistoffset*/
-#endif
0, /*tp_iter*/
0, /*tp_iternext*/
DBusPyServer_tp_methods,/*tp_methods*/
Index: dbus-python/test/test-client.py
===================================================================
--- dbus-python.orig/test/test-client.py
+++ dbus-python/test/test-client.py
@@ -110,6 +110,22 @@ class TestDBusBindings(unittest.TestCase
del bus
self.assertTrue(ref() is None)
+ def testWeakRefsToBaseConnection(self):
+ # dbus.SessionBus() is a Python subclass, which always has
+ # Py_TPFLAGS_HAVE_GC; the C types do not, so they need their own
+ # coverage. Marking a non-GC type Py_TPFLAGS_MANAGED_WEAKREF makes
+ # CPython look for the weakref slot in the PyGC_Head that was never
+ # allocated, which reads and writes off the front of the object.
+ address = os.environ['DBUS_SESSION_BUS_ADDRESS']
+ conn = _dbus_bindings.Connection(address)
+ try:
+ ref = weakref.ref(conn)
+ self.assertTrue(ref() is conn)
+ finally:
+ conn.close()
+ del conn
+ self.assertTrue(ref() is None)
+
def testInterfaceKeyword(self):
#test dbus_interface parameter
print(self.remote_object.Echo("dbus_interface on Proxy test Passed",
signature.asc
Description: PGP signature
--- End Message ---