Что происходит с другими потоками, когда один поток forks()?

В С++ с использованием pthreads, что происходит с вашими другими потоками, если один из ваших потоков вызывает fork?

Похоже, что нити не следуют. В моем случае я пытаюсь создать демона, и я использую fork() с родительским выходом, чтобы деамонизировать его. Однако в новом пути через код я создаю некоторые потоки перед вилкой, а некоторые после. Есть ли простой способ изменить принадлежность потоков к новому разветвленному процессу, а не перемещать все мои создания потоков после fork?

Ответ 1

Ничего. Только поток, вызывающий fork(), получает дубликат. Детский процесс должен начинать любые новые потоки. Потоки родителей остались одни.

Ответ 2

Обычно очень плохо разветвлять поток. Предполагается, что разветвленный процесс является полной копией родителя, кроме как с потоками это не так. Существует функция pthread_atfork(), которая иногда помогает. Если вы должны разветкить поток, лучше всего, если вы вызываете exec() сразу после fork().

Я предлагаю вам прочитать оговорки от разработчиков POSIX в документации fork() и pthread_atfork() (см. http://pubs.opengroup.org/onlinepubs/007904975/functions/fork.html и http://pubs.opengroup.org/onlinepubs/007904975/functions/pthread_atfork.html).

Из документации fork():

Таким образом, функция fork() используется только для запуска новых программ, а эффекты вызывающих функций, требующие определенных ресурсов между вызовом fork() и вызовом функции exec, - это undefined.

Ответ 4

Ничего, если только кто-то не будет вытеснен потоком, запускающим новый процесс.

Ответ 5

В POSIX, когда многопоточный процесс вилки, дочерний процесс выглядит точно как копия родителя, но в котором все потоки остановились на своих дорожках и исчезли.

Это очень плохо, если в потоках хранятся блокировки.

По этой причине существует грубый механизм, называемый pthread_atfork, в котором вы можете зарегистрировать обработчики для этой ситуации.

Любой правильно написанный программный модуль (и особенно многоразовое промежуточное ПО), который использует мьютексы, должен вызывать pthread_atfork для регистрации некоторых обработчиков, чтобы он не ошибался, если процесс вызывает вызов fork.

Помимо блокировок mutex, потоки могут иметь другие ресурсы, такие как данные, специфичные для потока, с помощью pthread_setspecific, которые доступны только для потока (и поток отвечает за очистку через деструктор).

В дочернем процессе такой деструктор не запускается. Адресное пространство копируется, но поток и его конкретное значение потока не существуют, поэтому память просочилась в дочерний элемент. Это можно и должно обрабатывать с помощью обработчиков pthread_atfork.