Я предполагаю, что вы отправляете сигнал в другой поток, потому что вы хотите выполнить некоторую работу, которая не может быть выполнена с помощью асинхронно-безопасных функций.
Проблема заключается в том, что если ваш обработчик сигнала вызывается наПоток, у которого были получены какие-либо блокировки (например, в вашем случае, внутренняя блокировка списка libio), тогда любой поток, который пытается получить такую же блокировку, будет блокироваться бесконечно: вы не можете вернуться из обработчика SIGSEGV, поэтому блокировка никогда не станет доступной дляблокировка снова, и ни один поток, ожидающий блокировки, не будет прогрессировать.В вашем случае, функция exit
должна получить блокировку списка libio, потому что она должна пройти через список всех открытых потоков файлов и очистить их, в то время как поток, открывающий новый файл, получает блокировку, в то время как он устанавливает новый файл всписок.
Несмотря на то, что это деталь реализации, которую можно было бы рассмотреть внутри glibc в какой-то (далекой) точке в будущем (небольшие улучшения, которые мы сделали относительно недавно, не помогут в вашем случае), единственнымВы можете вызвать _exit
перед завершающей процедурой выхода из процесса в glibc, после очистки, которую вам нужно сделать.В вашем случае это можно сделать с помощью обработчика atexit
, который вы зарегистрировали как можно раньше, но это зависит от вашего приложения.
Что касается обработчиков сбоя, мы опубликовали здесь несколько советов:
В статье рассматривается fork
, но проблемы взаимоблокировок практически одинаковы в вашем случае.