# Interesting Facts of Pthread ## Fact 0 :::info :bulb: Calling pthread_exit on main thread may block when the jobs executed by other threads do not complete ::: ```cpp= #include <pthread.h> #include <stdio.h> #include <unistd.h> void *looping(void *args) { (void) args; for (;;) { // Looping printf("Running loop ...\n"); sleep(1); } } int main(void) { printf("Creating the thread ...\n"); pthread_t loop; pthread_create(&loop, NULL, looping, NULL); pthread_exit(NULL); } ``` It may exit immediately if we replace line 24 with `return 0`. ## Fact 1 :::info :bulb: Checking the return values of pthread_attr_init and pthread_attr_destroy is unneccessary ::: According to the manual pthread_attr_init(3): > **RETURN VALUE** > On success, these functions return 0; on error, they return a nonzero error number. > > **ERRORS** > POSIX.1 documents an ENOMEM error for pthread_attr_init(); on Linux these functions always succeed (but portable and future-proof applications should nevertheless handle a possible error return). Which means that it will always success on Linux ## Fact 2 :::info :bulb: pthread_attr_t should be destroyed after used ::: This is a feature introduced at v2.3.2 [^glibc2.3.2] to enqueue the address of each pthread_attr_t into a global list when debugging pthread library [^glibc2.3.2]: [glibc-2.3.2/source/nptl/pthread_attr_init.c#L51](https://elixir.bootlin.com/glibc/glibc-2.3.2/source/nptl/pthread_attr_init.c#L51) ```cpp int __pthread_attr_init_2_1 (attr) pthread_attr_t *attr; { struct pthread_attr *iattr; /* Many elements are initialized to zero so let us do it all at once. This also takes care of clearing the bytes which are not internally used. */ memset (attr, '\0', __SIZEOF_PTHREAD_ATTR_T); assert (sizeof (*attr) >= sizeof (struct pthread_attr)); iattr = (struct pthread_attr *) attr; /* Default guard size specified by the standard. */ iattr->guardsize = __getpagesize (); /* Enqueue the attributes to the list of all known variables. */ if (DEBUGGING_P) { lll_lock (__attr_list_lock); iattr->next = __attr_list; __attr_list = iattr; lll_unlock (__attr_list_lock); } return 0; } versioned_symbol (libpthread, __pthread_attr_init_2_1, pthread_attr_init, GLIBC_2_1); ``` But it seems to be removed at v.2.3.4 [^glibc2.3.4]. Leaving the global list `__attr_list` unused. [^glibc2.3.4]: [glibc-2.3.4/source/nptl/pthread_attr_init.c#L49](https://elixir.bootlin.com/glibc/glibc-2.3.4/source/nptl/pthread_attr_init.c#L49) ## Fact 3 :::info :bulb: Threads may be considered as zombie if you do not handle the exit of each thread before exiting the main thread :::