I'm curious how a single NPTL thread exits, from implementation perspective.
What I understand about glibc-2.30 's implementation are:
_exit()
syscall kills all threads in a thread group. pthread_create()
takes in is actually wrapped into another function start_thread()
, which does some preparation before running the user function, and some cleaning up afterwards. Questions are:
At the end of the wrapper function start_thread()
, there are the following comment and code:
/* We cannot call '_exit' here. '_exit' will terminate the process. The 'exit' implementation in the kernel will signal when the process is really dead since 'clone' got passed the CLONE_CHILD_CLEARTID flag. The 'tid' field in the TCB will be set to zero. The exit code is zero since in case all threads exit by calling 'pthread_exit' the exit status must be 0 (zero). */ __exit_thread ();
but __exit_thread()
seems to do syscall _exit()
anyways:
static inline void __attribute__ ((noreturn, always_inline, unused)) __exit_thread (void) { /* some comments here */ while (1) { INTERNAL_SYSCALL_DECL (err); INTERNAL_SYSCALL (exit, err, 1, 0); } }
so I'm confused here, since it shouldn't really do syscall _exit()
because it will terminate all threads.
pthread_exit()
should terminate a single thread, so it should do something similar to what the wrapper start_thread()
does in the end, however it calls __do_cancel()
, and TBH I am lost in tracing down that function. It does not seem to be related to the above __exit_thread()
, nor does it call _exit()
.I'm confused here, since it shouldn't really do syscall _exit()
The confusion here stems from mixing exit
system call with _exit
libc routine (there is no _exit
system call on Linux).
The former terminates current Linux thread (as intended).
The latter (confusingly) doesn't execute exit
system call. Rather, it executes exit_group
system call, which terminates all threads.
thread_exit() should terminate a single thread
It does, indirectly. It unwinds current stack (similar to siglongjmp
), performing control transfer to the point where cleanup_jmp_buf
was set up. And that was in start_thread
.
After the control transfer, start_thread
cleans up resources, and calls __exit_thread
to actually terminate the thread.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.