Ответ 1
Ничего. Только поток, вызывающий fork(), получает дубликат. Детский процесс должен начинать любые новые потоки. Потоки родителей остались одни.
В С++ с использованием pthreads, что происходит с вашими другими потоками, если один из ваших потоков вызывает fork?
Похоже, что нити не следуют. В моем случае я пытаюсь создать демона, и я использую fork() с родительским выходом, чтобы деамонизировать его. Однако в новом пути через код я создаю некоторые потоки перед вилкой, а некоторые после. Есть ли простой способ изменить принадлежность потоков к новому разветвленному процессу, а не перемещать все мои создания потоков после fork?
Ничего. Только поток, вызывающий fork(), получает дубликат. Детский процесс должен начинать любые новые потоки. Потоки родителей остались одни.
Обычно очень плохо разветвлять поток. Предполагается, что разветвленный процесс является полной копией родителя, кроме как с потоками это не так. Существует функция 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.
Цитата из http://thorstenball.com/blog/2014/10/13/why-threads-cant-fork/
If we call fork(2) in a multi-threaded environment the thread doing the call is now the main-thread in the new process and all the other threads, which ran in the parent process, are dead. And everything they did was left exactly as it was just before the call to fork(2).
Ничего, если только кто-то не будет вытеснен потоком, запускающим новый процесс.
В POSIX, когда многопоточный процесс вилки, дочерний процесс выглядит точно как копия родителя, но в котором все потоки остановились на своих дорожках и исчезли.
Это очень плохо, если в потоках хранятся блокировки.
По этой причине существует грубый механизм, называемый pthread_atfork
, в котором вы можете зарегистрировать обработчики для этой ситуации.
Любой правильно написанный программный модуль (и особенно многоразовое промежуточное ПО), который использует мьютексы, должен вызывать pthread_atfork
для регистрации некоторых обработчиков, чтобы он не ошибался, если процесс вызывает вызов fork
.
Помимо блокировок mutex, потоки могут иметь другие ресурсы, такие как данные, специфичные для потока, с помощью pthread_setspecific
, которые доступны только для потока (и поток отвечает за очистку через деструктор).
В дочернем процессе такой деструктор не запускается. Адресное пространство копируется, но поток и его конкретное значение потока не существуют, поэтому память просочилась в дочерний элемент. Это можно и должно обрабатывать с помощью обработчиков pthread_atfork
.