Its difficult to describe this as a library bug.
What is happening.
thread_local std::thread asd
This is in a thread, creates a thread and stores it in thread local storage.
When thread t2
completes, it starts the thread destruction process. This process is naturally single threaded - 2 threads can't end at the same time, and they get serialized.
The threaded mechanisms note that there is thread_local
storage for that thread, and start calling the destructor for asd, which includes invoking the join
function.
So we wait for asd to be able to complete. Unfortunately it is unable to do this, as the thread destruction of asd
is blocked by the thread t2
- which is in progress. Hence the deadlock.
Fixes.
- Store item asd in normal memory, not thread local.
- join asd before the end of
t2
's function.
- Ensure that asd has run before getting to the end of t2.
The library writers have a really difficult set of goals to achieve. They need to ensure that thread-local data is tidied up in a timely manner. If thread local destruction is delayed until after the thread is finished, referred to data which went out of scope with the thread, there would be bugs.
If they (as implemented), tidied up in the context where the thread is in the process of being destroyed, they face this form of inter-thread deadlock.
Update
Running on linux (wasn't sure what Clang and GCC meant apart from linux),
I confirmed that the program as is,
- Ran the constructed asd thread before the t2 thread completed
- Delaying execution of the
asd
thread showed the destruction of thread_local asd
didn't slow or stop the destruction of thread-local-storage data (__GI__call_tls_dtors
)
So I would say that the linux implementation has issues where a thread stored in thread_local
may refer to other thread_local
data which may be destroyed.
The use of thread_local
for asd
is completely unnecessary, and is the cause of the problem