`pthread_detach(0)` segfaults instead of returning ESRCH

ghz 8months ago ⋅ 59 views

I've come across some unexpected behaviour with pthread_detach. Consider the following code:

#include <pthread.h>

int main() {
    pthread_detach(0);
}

It's obviously an error (0 is not a valid pthread_t). When I run this code, the process crashes with a segfault.

The problem is that, according to the man page, it should handle this error and simply return ESRCH (since this should just be a case of "no thread with ID 0 found", right?)

The only undefined behaviour mentioned by the man page is when attempting to detach an already detached thread, which this isn't.

I'm using glibc version 2.39-4.2; could this be a bug?

Update: I've found the code responsible for this, here: https://elixir.bootlin.com/glibc/glibc-2.39/source/nptl/pthread_detach.c#L29

So it seems that "thread ID" in the man page refers to some property (tid, see here) of the thread structure (which is pointed to by the pthread_t type. This explains the segfault, but I'm still not convinced this is expected behaviour.

Update 2: I just came across this very related question, which seems to pretty much answer this one.

Answers

It appears that you've encountered unexpected behavior when using pthread_detach with an invalid thread ID. While the behavior you observed may seem surprising, it's not necessarily a bug in glibc; rather, it's a consequence of how pthread_detach is implemented.

When you pass an invalid thread ID (in this case, 0) to pthread_detach, the function tries to access the thread structure associated with that ID. However, since 0 is not a valid thread ID, this results in a segmentation fault.

The behavior you expected, where pthread_detach returns ESRCH (indicating that no thread with the specified ID was found), is not mandated by the POSIX standard. Instead, POSIX specifies that passing an invalid thread ID to pthread_detach results in undefined behavior. This means that the behavior can vary between different implementations of the POSIX threading API, and it's not guaranteed to be consistent or predictable.

In practice, it's generally a good idea to ensure that you're passing valid thread IDs to pthread_detach to avoid encountering undefined behavior. If you're unsure whether a thread ID is valid, you can use pthread_equal to compare it against the result of pthread_self to check if it corresponds to the current thread.