| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Программирование под Unix/Linux > signal & setjmp / longjmp |
| Автор: null56 19.3.2008, 19:32 | ||
| Проблема возникла не у меня, у моего коллеги... и конечно я посоветовал ему лучше отладить свой код... но он ни в какую... Задача состоит в том, чтобы отловить segmentation fault и не вылетать из программы, а просто проигнорировать этот момент и продолжить со следующей итерации... Вчера познакомился с макросами setjmp и longjmp, но их работа по видимому осталась для меня загадкой... Приведу пример кода, над которым я ставлю эксперименты
Первая итерация отрабатывает, как надо... Но на второй, судя по дебагеру теряется адрес обработчика сигнала и программа вылетает на этапе генерации прерывания, а именно на строке *pTest = 123; Объясните пожалуйста, где моя ошибка... Судя по всему я просто не правильно понимаю работу этих макросов... Заранее благодарен всем откликнувшимся за помощь... |
| Автор: creatorcode 19.3.2008, 19:48 | ||||
pTest - нулевой указатель, поэтому и вылетает с ошибкой. Вы должны сначала выделить память под указатель и только потом использовать его. Например так:
где size - размер выделяемой памяти. В вашем случае по всей видимости size=1. Хотя тогда непонятно с какой вообще целью используется указатель. |
| Автор: MAKCim 19.3.2008, 19:52 |
| не вижу ошибки у меня все сводится к бесконечному циклу, т. е как и должно быть Добавлено через 44 секунды creatorcode, вы не в теме, извините |
| Автор: creatorcode 19.3.2008, 20:05 | ||||
Прошу прощения, не сразу въехал в вопрос. Попробую оправдаться
К тому же не вижу смысла использовать signal. Можно вполне обойтись и без него:
|
| Автор: null56 19.3.2008, 20:17 | ||||
| MAKCim, Вы попробовали запускать этот код? Потому что у меня там ожидание стоит между циклами 5 секунд, а ошибка вылетает на ВТОРОЙ (!!!) итерации цикла? Приведу пример код с отладочной печатью...
Результатом работы будет:
|
| Автор: null56 19.3.2008, 22:50 | ||
Аналогичная программа, использующая обычный метод не вылетает...
В чем хитрость... в какой области памяти создается функция, которая назначается методом signal? |
| Автор: MAKCim 19.3.2008, 23:13 | ||||
| null56, вообщем, все понятно сначала решение чтобы все заработало, нужно использовать sigsetjmp() и siglongjmp() теперь почему не работало следите за логикой 1. при формировании ядром сигнального фрейма, в стек записывается адрес возврата т. е когда выполняется код обработчика SIGSEGV на вершине стека лежит адрес возврата при вызове signal() мы не можем его явно указать, поэтому код libc, которому соответствует функция signal() устанавливает его за нас по-умолчанию адрес возврата, указываемый в libc, соответствует внутренней функции libc, которая осуществляет восстановление контекста процесса исходя из данных, которые ядро сохранило для нас в сигнальном фрейме 2. на первой итерации SIGSEGV успешно перехватывается и управление переходит на наш обработчик но вместо того, чтобы перейти по адресу, находящемуся на вершине стека, идет вызов longjmp(), который полностью восстанавливает контекст процесса важно отметить, что ядро перед вызовом обработчика сигнала блокирует этот сигнал поэтому после longjmp() мы оказываемся тут
и при этом SIGSEGV заблокирован 3. генерация сигнала для процесса в результате #PF осуществляется в функции ядра force_sig_info() вот ее код
ключевой момент зключается в том, что в ней идет проверка, не заблокирован ли генерируемый сигнал и если заблокирован (а в нашем случае он заблокирован, как я показал выше), то он разблокируется с восстановлением дефолтного состояния обработчика сигнала, которым является SIG_DFL для SIGSEGV дефолный обработчик приводит к завершению процесса поэтому на второй итерации идет завершение процесса, а не передача управления на наш обработчик sigsetjmp() сохраняет маску заблокированных к моменту вызова сигналов (на первой итерации SIGSEGV еще не заблокирован) siglongjmp() восстанавливает маску заблокированных сигналов а значит после siglongjmp() SIGSEGV не будет заблокирован и в функции force_sig_info() не произойдет сброс нашего обработчика |
| Автор: null56 20.3.2008, 01:08 |
| Огромное спасибо за помощь... Я понял свою ошибку, она в большинстве своем все - таки была от незнания... Действительно, создавая непосредсвенный переход на свою точку в стеке, я теряю обратный ход событий, который подразумевал в libc вызов своих процедур, которые отвечали за разблокировку сигнала. Еще раз спасибо всем откликнувшимся... ЗЫ: MAKCim, я вопрос не по теме отправил вам в личку |
| Автор: xvr 20.3.2008, 13:06 | ||||
Я бы еще добавил по поводу signal:
|