я могу изменить pthread_create для отображения новых потоков не в стеке? - PullRequest
1 голос
/ 06 апреля 2020

Я использую библиотеку pthread.h в glibc-2.27, и когда мой процесс вызывает pthread_create() восемнадцать раз или более (это должно быть тяжелое многопоточное приложение), процесс прерывается с сообщением об ошибке:

*** stack smashing detected ***: <unknown> terminated
Aborted (core dumped)

Я сделал strace как часть моего ритуала отладки, и я нашел причину. Очевидно, что все неявные вызовы для mmap() как часть pthread_create() выглядят так:

mmap(NULL, 8392704, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0x7f6de43fa000

Можно заметить флаг MAP_STACK, который указывает:

Выделить отображение по адресу, подходящему для процесса или стека потока. Этот флаг в настоящее время не используется, но используется в реализации потоков glib c, поэтому, если некоторые архитектуры требуют особого подхода к распределению стека, позднее поддержка прозрачно может быть реализована для glib c.

(man mmap в моей системе - Ubuntu 18.04 LTS)

Возможно ли настроить вызов pthread_create, чтобы не делать этого? или, может быть, используйте brk или что-то еще для автоматического увеличения сегмента данных?

Спасибо за любую помощь!

Ответы [ 2 ]

3 голосов
/ 06 апреля 2020

Крайне маловероятно, что ваша проблема связана с этим флагом MAP_STACK.

У вас есть ошибка где-то еще в вашем приложении, которая вызывает повреждение стека. Попробуйте запустить приложение под valgrind или создать с -fsanitize=address. Любой из этих подходов может точно определить точное местоположение ошибки, и вы сможете выяснить, что не так, основываясь на этом.

2 голосов
/ 07 апреля 2020

Можно ли настроить вызов pthread_create, чтобы он этого не делал?

pthread_create() необходимо выделить место для стека потока, иначе поток не сможет работать - даже с функция пустого потока. Вот для чего mmap вы видите. Невозможно обойтись без.

или, возможно, использовать brk или что-то еще для автоматического увеличения сегмента данных?

Если у вас есть время и умение написать свой собственную библиотеку потоков, тогда у вас есть go и дайте нам знать, что происходит. В противном случае, нет, детали того, как pthread_create() резервирует пространство для стека нового потока, не конфигурируются ни в одной из известных мне реализаций.

И это не имеет значения, так как вызов mmap() не является проблемой , Если системный вызов имеет неисправимый сбой, то это сбой ядра, и вы получаете ядро ​​pani c, а не приложение cra sh. Обнаружение разрушения стека в GNU C происходит в пользовательском пространстве. Поэтому функции, к которым он применяется, не отображаются в выходных данных strace, которые отслеживают только системные вызовы .

. Возможно, вам будет полезно лучше разбить стек и защитить GNU от Это. Доктор Добб опубликовал хорошую статью о том, что несколько лет go, и это все еще стоит прочитать. Суть в том, что разрушение стека происходит, когда реализация функции ведет себя неправильно, перезаписывая ту часть своего стекового фрейма, которая содержит адрес возврата. Если у вас нет встроенной сборки, разрушение почти наверняка происходит из-за того, что одна из ваших собственных функций выходит за пределы одной из ее локальных переменных. Он обнаруживается, когда эта функция пытается вернуться, используя инструментальный эпилог функции, который служит этой цели.

...