On Sat, Nov 07, 2026 at 01:09:03PM +0100, Pepper Gray wrote:
> According to POSIX, self-joining a thread is undefined behavior:
> 
> > The behavior is undefined if the value specified by the thread argument to
> > pthread_join() refers to the calling thread.
> 
> ```C
> #include <pthread.h>
> #include <stdio.h>
> #include <string.h>
> 
> int main(void) {
>   int err = pthread_join(pthread_self(), NULL); // glibc: EDEADLK,
> musl: never returns
>   printf("returned: %s\n", strerror(err));
> }
> ```
> 
> but the rationale recommends detecting it:
> 
> > If an implementation detects that the value specified by the thread argument
> > to pthread_join() refers to the calling thread, it is recommended that the
> > function should fail and report an [EDEADLK] error.
> 
> This is the case in `glibc`, which reports `EDEADLK` while musl just hangs.
> 
> While hanging is technically correct, the behavior is undesirable in practice,
> and a behavior like returning `EDEADLK` or even crashing would make it easier 
> to
> deal with such an app than when it just hangs.

It's very intentional that we do not facilitate forward progress when
a program has invoked undefined behavior. There is no good reason to
expect that a programmer has ignored the fact that the operation is UB
will have taken the effort to check the return value, so just
returning an error is likely to result in the flow of execution
continuing to run in an inconsistent and possibly dangerous state.

Self-join suggests a confusion about who owns resources, so this may
involve data races, etc. But this is a pretty broad principle in musl,
not specific to pthread_join. At one point my write-up of the
principle was included in some glibc guidelines too; I can't find the
link to that at the moment, but FWIW there was consensus that "return
an error on UB" is bad behavior.

> In C++ this case is defined for `std::thread::join()`
> ([thread.thread.member](https://eel.is/c++draft/thread.thread.member)):
> 
> > *Throws:* `system_error` when an exception is required 
> > ([thread.req.exception]).
> >
> > *Error conditions:*
> > - `resource_deadlock_would_occur` — if deadlock is detected or `get_id() == 
> > this_thread::get_id()`.
> 
> However this doesn't work on `libstdc++` nor `libc++` because they both wrap
> `pthread_join`, which just hangs on musl.

If the C++ std::thread::join has a contract to throw on self-join then
it needs to call pthread_equal before pthread_join to check that
condition.

Reply via email to