Как вы, возможно, знаете, все потоки в приложении умирают в разветвленном процессе, кроме потока, делающего вилку. Тем не менее, я планирую повторить эти потоки в разветвленном процессе, вызвав pthread_create и используя pthread_attr_setstack , чтобы назначить вновь созданные потоки тем же самым стекм, что и мертвые потоки. Что-то вроде следующего.
// stackAddr and stacksize taken from the dead thread
pthread_attr_setstack(&attr, stackAddr, stacksize);
rc = pthread_create(&thread, &attr, threadRoutine, NULL);
Тем не менее, мне все равно нужно получить значения регистров процессора, такие как указатель стека, указатель базы данных, указатель инструкций и т. Д., Для перезапуска потоков из одной и той же точки. Как я могу это сделать? И что еще мне нужно сделать, чтобы успешно достичь моей цели?
Также обратите внимание, что я использую 64-битную архитектуру. Какие дополнительные трудности у него будут по сравнению с 32-битными?
Я вижу два возможных способа стрелять себе в ногу и терять волосы. W: W ^ W ^ W ^ W ^ W ^ W ^ Wtry сделать это:
getcontext ()
перед fork ()
, а затем восстанавливать контекст каждого потока через setcontext () . Наверное, это не сработает, но вы можете попробовать развлечься.
ptrace (PTRACE_GETREGS)
, ptrace (PTRACE_GETFPREGS)
и восстановить с помощью ptrace (PTRACE_SETREGS)
, ptrace (PTRACE_SETFPREGS) .
Другие потоки текущего процесса не будут уничтожены вилкой - они все еще существуют и работают в родительском. Проблема, с которой вам кажется, заключается в том, что fork
только разворачивает поток SINGLE в текущие процессы, создавая новый процесс с одним потоком с копией всех ресурсов, отличных от потока, в родительском.
То, что вы, по-видимому, хотите, - это способ дублирования всей многопоточной задачи, разворачивания всех потоков в ней и создания нового процесса/задачи с тем же количеством потоков.
Чтобы сделать это, вам нужно будет найти и приостановить все остальные потоки процесса, сбросить их текущее состояние (включая все блокировки, которые они хранят), развернуть новый процесс и затем (повторно) создать каждый из этих других потоков в дочерний элемент, переписывая состояние блокировки, чтобы ссылаться на новые дочерние потоки, где это необходимо.
К сожалению, интерфейс POSIX pthread безнадежно неопределен и не дает никакого способа сделать это. В частности, в нем отсутствует какой-либо отражающий интерфейс, позволяющий выяснить, какие потоки фактически выполняются.
Если вы все равно попытаетесь сделать это, я вижу два способа попытаться приблизиться к этому:
выкарабкается в/proc/self/task, чтобы выяснить, какие потоки выполняются в вашем процессе, эффективно используя этот отражающий интерфейс очень не переносимым образом. Вероятно, в конечном итоге вам придется использовать (2) другие потоки, чтобы получить их внутреннее состояние. Это будет очень сложно.
оберните библиотеку pthreads - вместо того, чтобы напрямую использовать библиотеку, перехватите каждый вызов и отслеживайте все созданные потоки/мьютексы/блокировки, чтобы у вас была доступная информация, если вы хотите использовать fork. Это будет работать нормально, если вы не хотите использовать сторонние библиотеки, которые используют pthreads
Второй вариант намного проще (и несколько портативен), но работает только хорошо, если у вас есть доступ ко всему исходному коду всего вашего приложения и его можно модифицировать для правильной работы ваших обертков.
Просто гуглинг вокруг я обнаружил, что солярис имеет вызов forkall (), который делает именно то, что вы хотите, см. Документацию здесь:
http://download.oracle.com /docs/cd/E19963-01/html/821-1601/gen-1.html
Я предполагаю, что вы работаете в Linux, но можно запустить solaris на оборудовании x86. Так что, возможно, это вариант для вас.