Package: src:python-pyinstrument Version: 5.1.2+ds-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 python-pyinstrument fails to build from source [1]. The error is: test/low_level/test_timing_thread.py Fatal Python error: Aborted An immediate abort is triggered due to a double release_lock, in Python 3.15 this is checked while in previous versions it wasn't. To fix it, I've added a patch that guards the call to PyThread_release_lock, checking the removals value. I've applied this fix in the sandbox [2] to verify that it builds successfully, please consider applying the patch to support the upcoming 3.15 version. This patch should also be forwarded upstream. 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/4598672/ [2]: 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: Maximiliano Curia <[email protected]> Date: Tue, 8 Sep 2026 11:52:35 +0200 Subject: timing_thread: Only release lock if a subscriber was removed Avoid releasing update_lock when unsubscribe is called on an already removed ID or when subscriber_count is already zero, which causes a crash on Python 3.15 due to unlocking an unlocked mutex. --- pyinstrument/low_level/pyi_timing_thread.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyinstrument/low_level/pyi_timing_thread.c b/pyinstrument/low_level/pyi_timing_thread.c index ebb9394..9c0ca82 100644 --- a/pyinstrument/low_level/pyi_timing_thread.c +++ b/pyinstrument/low_level/pyi_timing_thread.c @@ -124,7 +124,7 @@ int pyi_timing_thread_unsubscribe(int id) { } // if the last subscriber was removed, stop the thread - if (subscriber_count == 0) { + if (removals > 0 && subscriber_count == 0) { thread_should_exit = 1; PyThread_release_lock(update_lock); thread_alive = 0;

