2010-06-10 2 views
1

Мне нужно обработать SIGSEGV в моем приложении Linux. Причиной является некоторая очистка (3-partry lib), которая должна быть выполнена перед генерированием дампа ядра. Более того, очистка должна выполняться в контексте вызывающего потока, не может выполняться в обработчике сигналов. Итак, я планирую обработчик сигнала передать управление вызывающему потоку после завершения очистки, а затем использовать raise (SIGSEGV) для создания ядро-дампа.ручка SIGSEGV в Linux?

Реальная проблема заключается в том, что signal_handler не может передать управление вызывающей нити, независимо от того, я использую post_sem или некоторые другие. Любая идея справиться с этим делом? Возможно, захватить SIGSEGV, а затем в SIGSEGV hander вернуться в другой поток, чтобы выполнить некоторую очистку?

сигнал (SIGSEGV, signal_handler);

signal_handler() { ... post_sem(); ... }

вызывающий поток() { wait_sem(); clean_up(); ... }

+0

Метод, который вы описали, на самом деле является самым близким к действительным. 'sem_post' (версия POSIX) требуется стандартом для обеспечения безопасности по асинхронному сигналу. –

ответ

2

Его не возможно надежного запуска любого кода после того, как вы столкнулись с SIGSEGV. Иногда вам может избежать неприятностей, но вы не можете доверять своей программе работать по назначению. Если, например, у вас есть SIGSEGV из-за поврежденной кучи, у вас возникнут проблемы, если ваша сторонняя библиотека очистит любую память.

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

1

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

Запись информации о состоянии, если это возможно, может помочь в отладке, но вы не должны полагаться на возможность.

Вместо этого программа должна после регистрации информации о состоянии либо вернуться к обработчику по умолчанию (и к дампу ядра и т. Д.), Либо вызвать _exit и выйти без какой-либо очистки.

Если вам нужно выполнить очистку, чтобы начать работу после аварии, сделайте это при следующем запуске.

3

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

По теме

Я думаю, вы могли бы попытаться заблокировать SIGSEGV во всех потоках, кроме тех, в которых вы пытаетесь выполнить очистку; это должно заставить os доставлять сигнал этому конкретному потоку. Другое решение, о котором я мог подумать, - это что-то вроде линий setjmp()/longjmp() (не проверял ни одно из них).

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

+0

Не поможет. «SIGSEGV» доставляется в конкретный поток, который вызвал недействительный доступ, а не процесс в целом. –