Вопрос

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

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

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

Есть какие-нибудь идеи?

Это было полезно?

Решение

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

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

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

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

Другие советы

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

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

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

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

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top