[Bug 285612] Qt thread deadlocks on destruction after fork()

From: <bugzilla-noreply_at_freebsd.org>
Date: Sun, 23 Mar 2025 17:24:42 UTC
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=285612

            Bug ID: 285612
           Summary: Qt thread deadlocks on destruction after fork()
           Product: Base System
           Version: CURRENT
          Hardware: Any
                OS: Any
            Status: New
          Severity: Affects Only Me
          Priority: ---
         Component: threads
          Assignee: threads@FreeBSD.org
          Reporter: arrowd@FreeBSD.org

Created attachment 258950
  --> https://bugs.freebsd.org/bugzilla/attachment.cgi?id=258950&action=edit
Testcase program

This bug was haunting me since Qt 5, but only now I was able to derive a
minimal testcase. I tried to replicate what Qt does to minimize even more, but
failed to do that - too much complex stuff contributes to this bug: forking,
threads, thread-local storage and __cxa_atexit.

When the test program is ran as

./a.out fork stuff

the program successfully terminates. However, running it as

./a.out stuff fork

makes the child hang in QDBusConnectionManager::~QDBusConnectionManager [1]. A
bit of debugging lead me to [2], which is an exceptionally complex piece of
code. By putting prints here and there I found out that the function passed
into pthread_cleanup_push in [3] does not get called in the 'stuff-fork' case.
Not sure if it's a problem or a symptom.

'fork-stuff':
set_thread_data(non-null)
destroy_current_thread_data
set_thread_data(non-null)
pthread_cleanup
destroy_current_thread_data
destroy_current_thread_data
set_thread_data(null)

'stuff-fork':
set_thread_data(non-null)
set_thread_data(non-null)

Since debugging this issue would require building Qt with debugging enabled,
here's a recipe on how to get a debugging env with Poudriere:

echo WITH_DEBUG_PORTS=devel/qt6-base >> /usr/local/etc/poudriere.d/make.conf
poudriere testport -j yourjail -p yourports -i devel/qt6-base

Then inside the jail:
fetch https://arrowd.name/t.cpp
head t.cpp (to get a c++ command line to compile the program

To apply some changes to Qt itself:

$EDITOR /wrkdirs/usr/ports/devel/qt6-base/work/...
make WITH_DEBUG=yes restage reinstall

[1]
https://github.com/qt/qtbase/blob/v6.8.2/src/dbus/qdbusconnectionmanager.cpp#L117
[2]
https://github.com/qt/qtbase/blob/v6.8.2/src/corelib/thread/qthread_unix.cpp#L82
[3]
https://github.com/qt/qtbase/blob/v6.8.2/src/corelib/thread/qthread_unix.cpp#L338

-- 
You are receiving this mail because:
You are the assignee for the bug.