# 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
:::