Воссоздать мертвые темы после разветвления

Как вы, возможно, знаете, все потоки в приложении умирают в разветвленном процессе, кроме потока, выполняющего разветвление. Однако я планирую восстановить эти потоки в разветвленном процессе, вызвав 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-битным?

7 голосов | спросил MetallicPriest 27 +04002011-10-27T19:42:22+04:00312011bEurope/MoscowThu, 27 Oct 2011 19:42:22 +0400 2011, 19:42:22

3 ответа


0

Я вижу два возможных способа выстрелить себе в ногу и потерять волосы. ^ W ^ W ^ W ^ W ^ W ^ W ^ W ^ Попробуйте сделать это:

  • Попробуйте заставить каждый поток вызывать getcontext() перед fork(), а затем восстановите контекст каждого потока с помощью setcontext(). Вероятно, не сработает, но вы можете попробовать для удовольствия.
  • Сохранить ptrace(PTRACE_GETREGS), ptrace(PTRACE_GETFPREGS), и восстановите с помощью ptrace(PTRACE_SETREGS), ptrace(PTRACE_SETFPREGS).
ответил ninjalj 27 +04002011-10-27T22:12:21+04:00312011bEurope/MoscowThu, 27 Oct 2011 22:12:21 +0400 2011, 22:12:21
0

Другие потоки в текущем процессе не уничтожаются вилкой - они все еще там и работают в родительском. Кажется, проблема в том, что fork разветвляет только ОДИН поток в текущих процессах, создавая новый процесс, выполняющий один поток с копией всех непотоковых ресурсов в родительском.

Очевидно, что вам нужен способ дублирования всей многопоточной задачи, разветвления всех потоков в ней и создания нового процесса /задачи с тем же числом потоков.

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

К сожалению, интерфейс POSIX pthread безнадежно недооценен, и не предоставляет никакого способа сделать это. В частности, в нем отсутствует какой-либо отражающий интерфейс, позволяющий выяснить, какие потоки действительно выполняются.

Если вы все-таки хотите попытаться это сделать, я вижу два способа сделать это:

  • покопайтесь в /proc /self /task, чтобы выяснить, какие потоки выполняются в вашем процессе, эффективно получая этот отражающий интерфейс в очень непереносимой форме. Скорее всего, вам придется в конечном итоге выполнить ptrace (2) для других потоков, чтобы получить их внутреннее состояние. Это будет очень сложно.

  • оберните библиотеку pthreads - вместо непосредственного использования библиотеки перехватывайте каждый вызов и отслеживайте все созданные потоки /мьютексы /блокировки, чтобы иметь эту информацию доступной, когда вы хотите выполнить форк. Это будет хорошо работать, если вы не хотите использовать сторонние библиотеки, которые используют pthreads

Второй вариант намного проще (и несколько переносим), но работает хорошо, только если у вас есть доступ ко всему исходному коду всего вашего приложения, и вы можете изменить его для правильного использования ваших оболочек.

ответил Chris Dodd 27 +04002011-10-27T22:17:02+04:00312011bEurope/MoscowThu, 27 Oct 2011 22:17:02 +0400 2011, 22:17:02
0

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

http: //download. oracle.com/docs/cd/E19963-01/html/821-1601/gen-1.html

Я предполагаю, что вы работаете в Linux, но возможно запустить Solaris на оборудовании x86. Так что, возможно, это вариант для вас.

ответил Kevin 27 +04002011-10-27T22:32:16+04:00312011bEurope/MoscowThu, 27 Oct 2011 22:32:16 +0400 2011, 22:32:16

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132