Загадочная проблема с вилкой () - PullRequest
3 голосов
/ 11 сентября 2009

У меня есть программа, которая:

  • имеет основной поток (1), который запускает серверный поток (2), а другой (4).
  • серверный поток (2) выполняет accept (), а затем создает новый поток (3) для обработки соединения.

В какой-то момент thread (4) выполняет fork / exec для запуска другой программы, которая должна подключиться к сокету, который прослушивает поток (2). Иногда это не удается или занимает неоправданно много времени, и это чрезвычайно трудно диагностировать. Если я использую систему, создается впечатление, что ответвление / exec сработало, произошло принятие, создан новый поток (4) ... но в этом потоке ничего не происходит (используя strace -ff, файл для соответствующего pid). пусто).

Есть идеи?

Ответы [ 5 ]

2 голосов
/ 14 сентября 2009

Я пришел к выводу, что, вероятно, это было явление:

http://kerneltrap.org/mailarchive/linux-kernel/2008/8/15/2950234/thread

, поскольку ошибку трудно вызвать в наших системах разработки, но обычно о ней сообщают пользователи, работающие на больших общих машинах; также разветвленное приложение запускает JVM, которая сама выделяет много потоков. Эта проблема также связана с загружаемой машиной и интенсивным использованием памяти (у нас есть машина с 128 ГБ ОЗУ и процессами размером 10-100 ГБ).

Я читал книгу pthreads O'Reilly, в которой объясняется pthread_atfork () и предлагается использовать процесс «суррогатного родителя», разветвленный из основного процесса при запуске, из которого запускаются подпроцессы. Также предлагается использовать предварительно созданный пул потоков. Обе эти идеи кажутся хорошими, поэтому я собираюсь реализовать хотя бы одну из них.

1 голос
/ 11 сентября 2009

Это похоже на тупиковую ситуацию. Ищите блокирующие функции, такие как accept (), проблема должна быть там.

0 голосов
/ 01 сентября 2010

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

Следующие правила взяты из "Мини-руководство по fork () и Pthreads" :

1- Вы НЕ ХОТИТЕ сделать это.

2- Если вам нужна fork (), тогда: по возможности, fork () все ваши childs до запуска любых потоков.

Редактировать: пробовал, fork () не дублирует потоки.

0 голосов
/ 11 сентября 2009

Будьте очень осторожны с несколькими нитями и вилкой. Большая часть glibc / libstdc ++ является поточно-ориентированной. Если поток, отличный от разветвляющегося потока, удерживает блокировку, когда форк выполняет разветвленный процесс, он унаследует мьютексы в их текущем заблокированном состоянии. Новый процесс никогда не увидит эти мьютексы разблокированными. Для получения дополнительной информации см man pthread_atfork.

0 голосов
/ 11 сентября 2009

Уменьшите код до минимально возможного размера, который все еще имеет поведение, и опубликуйте его здесь. Либо вы найдете ответ, либо мы сможем его найти.

КСТАТИ - http://lists.samba.org/archive/linux/2002-February/002171.html похоже, что поведение pthread для exec не очень хорошо определено и может зависеть от вашей ОС.

Есть ли у вас код между fork и exec? Это может быть проблемой.

...