Библиотека pthreads (на Linux, NPTL) предоставляет оболочку для примитивов более низкого уровня, таких как clone(2)
. Когда поток создается с помощью pthread_create
, функция, переданная в clone
, является функцией-оболочкой. Эта функция выделяет стек и сохраняет эту информацию, а также любые другие метаданные в структуре, а затем вызывает предоставленную пользователем функцию запуска. Когда пользовательская функция запуска возвращается, происходит очистка. Наконец, внутренняя функция с именем __exit_thread
вызывается для выполнения системного вызова для выхода из потока.
Когда такой поток отсоединяется, он все равно возвращается из предоставленной пользователем функции запуска и вызывает код очистки как раньше, за исключением того, что стек и метаданные освобождаются как часть этого, так как никто не ждет завершения этого потока. Обычно это обрабатывается pthread_join
.
Если поток завершается или завершается без запуска, то очистка обрабатывается следующим вызовом pthread_create
, который вызовет любые обработчики очистки, которые еще не запущены. .
Причина, по которой SIGCHLD
не отправляется родительскому элементу и не требуется wait(2)
, заключается в том, что используется флаг CLONE_THREAD
для clone(2)
. На странице руководства об этом флаге говорится следующее:
Новый поток, созданный с помощью CLONE_THREAD, имеет тот же родительский процесс, что и процесс, который вызвал клонирование (например, как CLONE_PARENT), так что вызовы getppid (2) вернуть одно и то же значение для всех потоков в группе потоков. Когда поток CLONE_THREAD завершается, поток, создавший его, не отправляет сигнал SIGCHLD (или другой сигнал завершения); также нельзя получить статус такого потока с помощью wait (2). (Говорят, что поток отсоединен.)
Как вы заметили, это необходимо для ожидаемой семантики POSIX.