How can one implement pthread_detach on Linux? - linux

pthread_detach marks a thread so that when it terminates, its resources are automatically released without requiring the parent thread to call pthread_join. How can it do this? From the perspective of Linux in particular, there are two resources in particular I am curious about:
As an implementation detail, I would expect that if a wait system call is not performed on the terminated thread, then the thread would become a zombie. I assume that the pthread library's solution to this problem does not involve SIGCHLD, because (I think) it still works regardless of what action the program has specified to occur when SIGCHLD is received.
Threads are created using the clone system call. The caller must allocate memory to serve as the child thread's stack area before calling clone. Elsewhere on Stack Overflow, it was recommended that the caller use mmap to allocate the stack for the child. How can the stack be unmapped after the thread exits?
It seems to me that pthread_detach must somehow provide solutions to both of these problems, otherwise, a program that spawns and detaches many threads would eventually lose the ability to continue spawning new threads, even though the detached threads may have terminated already.

The pthreads library (on Linux, NPTL) provides a wrapper around lower-level primitives such as clone(2). When a thread is created with pthread_create, the function passed to clone is a wrapper function. That function allocates the stack and stores that information plus any other metadata into a structure, then calls the user-provided start function. When the user-provided start function returns, cleanup happens. Finally, an internal function called __exit_thread is called to make a system call to exit the thread.
When such a thread is detached, it still returns from the user-provided start function and calls the cleanup code as before, except the stack and metadata is freed as part of this since there is nobody waiting for this thread to complete. This would normally be handled by pthread_join.
If a thread is killed or exits without having run, then the cleanup is handled by the next pthread_create call, which will call any cleanup handlers yet to be run.
The reason a SIGCHLD is not sent to the parent nor is wait(2) required is because the CLONE_THREAD flag to clone(2) is used. The manual page says the following about this flag:
A new thread created with CLONE_THREAD has the same parent process as the process that made the clone call (i.e., like CLONE_PARENT), so that calls to getppid(2) return the same value for all of the threads in a thread group. When a CLONE_THREAD thread terminates, the thread that created it is not sent a SIGCHLD (or other termination) signal; nor can the status of such a thread be obtained using wait(2). (The thread is said to be detached.)
As you noted, this is required for the expected POSIX semantics to occur.

Related

How to detect if a linux thread is crashed

I've this problem, I need to understand if a Linux thread is running or not due to crash and not for normal exit. The reason to do that is try to restart the thread without reset\restart all system.
The pthread_join() seems not a good option because I've several thread to monitoring and the function return on specific thread, It doesn't work in "parallel". At moment I've a keeep live signal from thread to main but I'm looking for some system call or thread attribute to understand the state
Any suggestion?
P
Thread "crashes"
How to detect if a linux thread is crashed
if (0) //...
That is, the only way that a pthreads thread can terminate abnormally while other threads in the process continue to run is via thread cancellation,* which is not well described as a "crash". In particular, if a signal is received whose effect is abnormal termination then the whole process terminates, not just the thread that handled the signal. Other kinds of errors do not cause threads to terminate.
On the other hand, if by "crash" you mean normal termination in response to the thread detecting an error condition, then you have no limitation on what the thread can do prior to terminating to communicate about its state. For example,
it could update a shared object that tracks information about your threads
it could write to a pipe designated for the purpose
it could raise a signal
If you like, you can use pthread_cleanup_push() to register thread cleanup handlers to help with that.
On the third hand, if you're asking about detecting live threads that are failing to make progress -- because they are deadlocked, for example -- then your best bet is probably to implement some form of heartbeat monitor. That would involve each thread you want to monitor periodically updating a shared object that tracks the time of each thread's last update. If a thread goes too long between beats then you can guess that it may be stalled. This requires you to instrument all the threads you want to monitor.
Thread cancellation
You should not use thread cancellation. But if you did, and if you include termination because of cancellation in your definition of "crash", then you still have all the options above available to you, but you must engage them by registering one or more cleanup handlers.
GNU-specific options
The main issues with using pthread_join() to check thread state are
it doesn't work for daemon threads, and
pthread_join() blocks until the specified thread terminates.
For daemon threads, you need one of the approaches already discussed, but for ordinary threads on GNU/Linux, Glibc provides non-standard pthread_tryjoin_np(), which performs a non-blocking attempt to join a thread, and also pthread_timedjoin_np(), which performs a join attempt with a timeout. If you are willing to rely on Glibc-specific functions then one of these might serve your purpose.
Linux-specific options
The Linux kernel makes per-process thread status information available via the /proc filesystem. See How to check the state of Linux threads?, for example. Do be aware, however, that the details vary a bit from one kernel version to another. And if you're planning to do this a lot, then also be aware that even though /proc is a virtual filesystem (so no physical disk is involved), you still access it via slow-ish I/O interfaces.
Any of the other alternatives is probably better than reading files in /proc. I mention it only for completeness.
Overall
I'm looking for some system call or thread attribute to understand the state
The pthreads API does not provide a "have you terminated?" function or any other such state-inquiry function, unless you count pthread_join(). If you want that then you need to roll your own, which you can do by means of some of the facilities already discussed.
*Do not use thread cancellation.

Calling fork on a multithreaded process

I had a doubt on using fork on a multi-threaded process.
If a process has multiple threads (already created using pthread_create and did a pthread_join) and I call fork, will it copy the same functions assigned to the threads in the child process or create a space where we can reassign the functions?
Read carefully what POSIX says about fork() and threads. In particular:
A process shall be created with a single thread. If a multi-threaded process calls fork(), the new process shall contain a replica of the calling thread and its entire address space, possibly including the states of mutexes and other resources. Consequently, to avoid errors, the child process may only execute async-signal-safe operations until such time as one of the exec functions is called.
The child process will have a single thread running in the context of the calling thread. Other parts of the original process may be tied up by threads that no longer exist (so mutexes may be locked, for example).
The rationale section (further down the linked page) says:
There are two reasons why POSIX programmers call fork(). One reason is to create a new thread of control within the same program (which was originally only possible in POSIX by creating a new process); the other is to create a new process running a different program. In the latter case, the call to fork() is soon followed by a call to one of the exec functions.
The general problem with making fork() work in a multi-threaded world is what to do with all of the threads. There are two alternatives. One is to copy all of the threads into the new process. This causes the programmer or implementation to deal with threads that are suspended on system calls or that might be about to execute system calls that should not be executed in the new process. The other alternative is to copy only the thread that calls fork(). This creates the difficulty that the state of process-local resources is usually held in process memory. If a thread that is not calling fork() holds a resource, that resource is never released in the child process because the thread whose job it is to release the resource does not exist in the child process.
When a programmer is writing a multi-threaded program, the first described use of fork(), creating new threads in the same program, is provided by the pthread_create() function. The fork() function is thus used only to run new programs, and the effects of calling functions that require certain resources between the call to fork() and the call to an exec function are undefined.

processes only terminate, when threads are terminated?

Processes should only terminate themselves, when all their threads are
terminated!
It's a question in our mock exam, and we aren't sure whether the statement is true or false.
Thanks a lot
First, I need to point out that this exam question contains an incorrect presumption. A running process always has at least one thread. The initial thread, the thread that first calls main or equivalent, isn't special; it's just like every other thread created by pthread_create or equivalent. Once all of the threads within a process have exited, the process can't do anything anymore — there's no way for it to execute even a single additional CPU instruction. In practice, the operating system will terminate the process at that point.
Second, as was pointed out in the comments on the question, the use of "should" makes your exam question ambiguous. It could be read as either "Processes only terminate when all of their threads are terminated" — as a description of how the system works. Or it could be read as "You, the programmer, should write code that ensures that your processes only terminate when all of their threads are terminated" — as a prescription for writing correct code.
If you are specifically talking about POSIX threads ("pthreads"), the answer to the descriptive question is that it depends on how each thread terminates. If all threads terminate by calling pthread_exit or by being cancelled, the process will survive until the last thread terminates, no matter which order they exit in. On the other hand, if any thread calls exit or _exit, or receives a fatal signal, that will immediately terminate the entire process, no matter how many threads are still active. (I am not 100% sure about this, but I think it doesn't matter whether any threads have been detached.)
There's an additional complication, which is that returning from a function passed to pthread_create is equivalent to calling pthread_exit for that thread, but returning from main is equivalent to calling exit. That makes the initial thread a little bit special: unless you specifically end main by calling pthread_exit, the entire process will be terminated when the initial thread exits. But technically this is not a property of the thread itself, but of the code running in that thread.
I do not know the answer to the descriptive question for threads libraries other than POSIX; in particular I don't know the answer for either Windows native threads, or for the threads library added to ISO C in its 2011 revision.
The answer to the prescriptive question is yes with exceptions. You, a programmer, should write programs that, under normal conditions, take care to end their process only when all of their threads have finished their work. (With POSIX threads, this translates to making sure that main does not return until all the other threads have been joined.) However, sometimes you have a few threads that run an infinite loop, without holding any locks or anything, and there's no good way to tell them to exit when everything else is done; as long as exiting the process out from under them won't damage any persistent state, go ahead and exit the process out from under them. (This is the intended use case for detached threads.) Also, it's OK, and often the best choice, to terminate the entire process abruptly if you encounter some kind of unrecoverable error. Those are the only exceptions I can think of off the top of my head.

Is pthread_join() a critical function?

According to POSIX, a Thread ID can be reused if the original bearer thread finished. Therefore, would one need to use a mutex or semaphore when calling pthread_join()? Because, it could happen that the target thread, which one wants to join, already terminated and another thread with the same thread ID was created, before calling pthread_join() in the original thread. This would make the original thread believe that the target thread has not finished, although this is not the case.
I think you'll find this works much the same way as processes in UNIX. A joinable thread is not considered truly finished until something has actually joined it.
This is similar to the UNIX processes in that, even though they've technically exited, enough status information (including the PID, which cannot be re-used yet) hangs around until another process does a wait on it. Only after that point does the PID become available for re-use. This kind of process is called a zombie, since it's dead but not dead.
This is supported by the pthread_join documentation which states:
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).
and pthread_create, which states:
Only when a terminated joinable thread has been joined are the last of its resources released back to the system.

Mixing threads, fork, and mutexes, what should I watch out for?

If I fork a process in which one thread holds a mutex, am I relatively safe if I immediately exec in the child? What things are safe to do in the child before I exec?
If the thread that executes fork then the child goes on to release a mutex before calling exec will this cause problems? What happens if I try to acquire a mutex in a child that the parent process owned before fork (and may or may not still own)?
Are the answers different on different platforms? I'm primarily concerned with Unix variants, and in particular Linux. But I am curious about NT. Though, of course, NT doesn't (to my knowledge) have fork.
See pthread_atfork, especially RATIONALE section, for a discussion of problems related to fork in multithreaded environment. It also gives a hint on what supposed to be valid before and after fork within a child and a parent.
UPDATE: the RATIONALE section is non-normative, and it turned out to be in conflict with other parts of the standard. See this defect report by Dave Butenhof for more details.
Immediate exec after fork is supposed to be safe for any state of multithreaded program (that is, any threads holding any mutexes). As of the things possible between fork and exec, the situation is complicated:
The most important thing is that only one thread (that which called fork) is duplicated in the child process. Consequently, any mutex held by another thread at the moment of fork becomes locked forever. That is (assuming non-process-shared mutexes) its copy in the child process is locked forever, because there is no thread to unlock it.
Releasing mutex after fork is safe when it's possible, that is, if the forking thread owns the mutex in the first place. That's how pthread_atfork handlers usually work: locking mutexes before fork, unlocking in child and unlocking in parent.
As of acquiring a mutex that the process owned before fork (remember, we discuss a copy in the child's address space): if it was owned by a forking thread, it's recursive locking (works for PTHREAD_MUTEX_RECURSIVE); if it was owned by another thread, it remains locked forever and can't be reacquired.
By registering appropriate pthread_atfork handlers, third-party libraries can provide a guarantee of being safe to use between fork and exec. (I would expect it mostly from programming language runtimes, not for general purpose libraries).
After some more research, I would recommend to avoid relying in any way on pthread_atfork, and doing nothing but async-signal-safe calls between fork and exec (abandoning fork/exec for posix_spawn would be even better).
The problem is, fork itself can be invoked in signal handler. It precludes any nontrivial use of pthread_atfork, even if its RATIONALE explicitly mentions unlocking mutexes and recreating threads (!) in a child process.
I think that a "grey area" of different possible interpretations remains:
For pthread_atfork handlers in a program which is known to never call fork in a signal handler.
For non-pthread-atfork actions happening around the fork call which is not in a signal handler.
But it's crystal clear which reading is to be used for portable applications.
It is safe to exec() after fork() provided the mutex is owned by the program that will get replaced by the exec(). If the mutex is part of a library and is protecting a resource that must be accessed serially then it should call pthread_atfork() to register callbacks:
A function that gets called prior to the fork itself and in the context of the thread that makes the fork() system call. Typically this function will grab the lock on mutexes that protect critical sections, thereby guaranteeing that during the fork no thread is inside a critical section
A function to be called in the context of the thread invoking fork(), after the child process has been created but before the fork() system call returns. This function can then unlock the mutexes in the parent process.
A function to be called in the context of the thread of the child process if/when the process forks - it gets called after the child process has been created but before the fork() system call returns. The child process can then unlock its copy of the mutex.
The POSIX standard limits the type of system calls that are allowed after a fork() and before an exec() to so called async-signal-safe system calls. Creating a thread isn't explicitly listed as an async-signal-safe system call, therefore POSIX doesn't allow a child process to create threads after a fork() and before exec(). Ironically, unlocking a mutex isn't explicitly listed as an async-signal-safe system call either, and thereofre isn't strictly allowed after a fork() in the child process if the intention of the fork() is to then exec() - probably an oversight in the standard.

Resources