pthread_join(3)

πŸ’… pthread_join(3) β€” the "bestie come BACK, I'm waiting" function

okay so real talk: this is pthread_join from the Library Functions Manual, and it lives in the POSIX threads library, aka libpthread, linked with -lpthread. she's the one who waits for your thread to finish so you can have closure (and free your memory). iconique behavior only.


✨ NAME ✨

pthread_join β€” join with a terminated thread

like, you go up to a thread and you're like "hey. when you're done. I'll be here. waiting." 🫢


πŸ“š LIBRARY πŸ“š

POSIX threads library β€” libpthread, -lpthread


🌸 SYNOPSIS 🌸

#include <pthread.h>

int pthread_join(pthread_t thread, void **retval);

that's it. two args. one function. so much power. πŸ‘‘


πŸ¦‹ DESCRIPTION πŸ¦‹

okay so the whole vibe here: pthread_join() waits for the thread specified by thread to terminate. and if that thread has already terminated? babes, it returns immediately. no waiting, no drama. she's efficient like that. ✨

BUT β€” and this is the plot twist β€” the thread specified by thread must be joinable. not detachable. joinable. keep that in mind, it comes up again later and it's kind of a big deal.

if retval is not NULL, then pthread_join() copies the exit status of the target thread β€” meaning the value that the target thread supplied to pthread_exit(3) β€” into the location pointed to by retval. so bestie hands over her whole story and you get the receipts. πŸ“

and if the target thread was canceled? then PTHREAD_CANCELED gets placed in the location pointed to by retval. so you always know what happened.

⚠️ now the messy part, and I need you to pay attention: if multiple threads simultaneously try to join with the same thread, the results are undefined. that's not a metaphor, that's just chaos. don't do it. πŸ’€
another one 🚨: if the thread calling pthread_join() is canceled, then the target thread will remain joinable β€” i.e., it will not be detached. so the cancellation doesn't clean up after itself. that's on you.

πŸŽ€ RETURN VALUE πŸŽ€

  • on success, pthread_join() returns 0 πŸ’–
  • on error, it returns an error number

(yes it returns the error number, not -1 and not errno. she's just built different.)


πŸ”₯ ERRORS πŸ”₯

  • EDEADLK β€” a deadlock was detected (e.g., two threads tried to join with each other 😭); or thread specifies the calling thread. yes, sitting in a chair waiting for yourself to get up. that's the vibe.
  • EINVAL β€” thread is not a joinable thread.
  • EINVAL β€” another thread is already waiting to join with this thread. (two people, one bestie. not allowed.)
  • ESRCH β€” no thread with the ID thread could be found. she's not here, she never was, ghosted. πŸ‘»

πŸ’œ ATTRIBUTES πŸ’œ

for an explanation of the terms used in this section, see attributes(7).

  • Interface: pthread_join()
  • Attribute: Thread safety
  • Value: MT-Safe
i.e. she's MT-Safe and you can trust her. βœ…

🌈 STANDARDS 🌈

POSIX.1-2008. certified. official. no cap.


⭐ HISTORY ⭐

POSIX.1-2001. she's been around and she's been doing this the whole time.


πŸ‘‘ NOTES πŸ‘‘

okay this is the extra-credit section, let's go:

  • after a successful call to pthread_join(), the caller is guaranteed that the target thread has terminated. pinky promise. 🫢
  • the caller may then choose to do any clean-up that is required after termination of the thread (e.g., freeing memory or other resources that were allocated to the target thread). this is your moment. go clean.
  • joining with a thread that has previously been joined results in undefined behavior. don't double-dip. 🚫
  • failure to join with a thread that is joinable (i.e., one that is not detached) produces a "zombie thread". avoid doing this, since each zombie thread consumes some system resources, and when enough zombie threads have accumulated, it will no longer be possible to create new threads (or processes). 🧟🧟🧟 like, real consequences. this is not a drill.
  • there is no pthreads analog of waitpid(-1, &status, 0), that is, "join with any terminated thread". if you believe you need this functionality, you probably need to rethink your application design. πŸ’€ (she said it, not me.)
  • all of the threads in a process are peers: any thread can join with any other thread in the process. no hierarchy, no gatekeeping, we're all equals here. 🌸

πŸ“ EXAMPLES πŸ“

see pthread_create(3). she's not gonna spell it out for you twice, the example lives over there. ✨


🧚 SEE ALSO 🧚


and that's the whole page, bestie πŸ’– this one's from Linux man-pages 6.20, dated 2025-05-17, and it's the pthread_join(3) page herself. go join your threads, free your memory, and please β€” for the love of everything β€” do not leave a zombie thread behind. πŸ§ŸπŸ’… mwah.

πŸ“¦ where this page comes from
  • arch rolling: man-pages 6.20-1 Β· BSD-2-Clause AND BSD-3-Clause AND BSD-4.3TAHOE AND BSD-4-Clause-UC AND GPL-1.0-or-later AND GPL-2.0-only AND GPL-2.0-or-later AND GPL-3.0-or-later AND LGPL-3.0-linking-exception AND LGPL-3.0-or-later AND LicenseRef-Public-Domain AND LicenseRef-UltraPermissive AND Linux-man-pages-1-para AND Linux-man-pages-copyleft AND Linux-man-pages-copyleft-2-para AND Linux-man-pages-copyleft-var AND MIT AND Spencer-94
  • nixpkgs unstable: man-pages 6.20
  • πŸ“œ the page's license: Linux-man-pages-copyleft
  • πŸ’– girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms