LINUX.ORG.RU

Обработка исключений


0

0

Пишу программу на C++ в Linux. Необходимо обрабатывать исключения типа выход за область памяти, причем не падая с сообщением Segmentation Fault. Такое событие удается отловить с помощью сигнала SIGSEGV. Но что делать дальше с приложением чтобы оно восстановило работу? Кто что посоветует?

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

anonymous
()

лолщито? «я прострелил себе башку, подскажите, что сделать, чтобы жизнь не заканчивалась!»

а ответ простой: гладиолус^W отлаживать надо.

engage
()
Ответ на: комментарий от anonymous

Но ведь как то это делают. Наверняка конечно не тривиально, но мне это не важно, главное это как то сделать. Хотя бы в каком направлении двигаться?

Silverj
() автор топика

Не нужно этого делать. Падать - самое правильное. И отрывать руки разработчику вторым шагом.

anonymous
()
Ответ на: комментарий от engage

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

Silverj
() автор топика
Ответ на: комментарий от Silverj

совет про падать относился к рамкам одного процесса -- если процесс получил SIGSEGV то сам он уже должен умирать. Но другие процессы его могут попытаться поднять заново. Как это делать -- это уже зависит от конкретной задачи.

dilmah ★★★★★
()
Ответ на: комментарий от Silverj

>Linux должен падать когда пользователь написал программу с делением на ноль?

что, прям таки весь линукс рушится? фигасе прикладной софт…

ну так а в чём проблема поймать сигнал от ребёнка «мне капец, приходил Гитлер!»? может, проблема в том, что маны на экране вверх тормашками, читать сложно?

engage
()
Ответ на: комментарий от Silverj

я всё это к тому, что «мусор на входе — мусор на выходе». поскольку вопрос поставлен нечётко (я обычно называю это «по идиотски», ну да ладно), то и никаких ответов, окромя гыгыканья, не будет. телепаты в отпуске, отттуда телеграфировали, что в ближайшие четыре эона их на работе не ждать.

engage
()
Ответ на: комментарий от engage

> я всё это к тому, что «мусор на входе — мусор на выходе». поскольку вопрос поставлен нечётко

Silverj
() автор топика
Ответ на: комментарий от engage

> я всё это к тому, что «мусор на входе — мусор на выходе». поскольку вопрос поставлен нечётко

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

Silverj
() автор топика
Ответ на: комментарий от Silverj

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

Ну вообще-то есть такие понятия как user-space и kernel-space. И возможности по работе с памятью соответственно разные. Если ядро ловит попытки выйти за выделенный кусок памяти и шлёт SIGSEGV юзерскому процессу, то далеко не факт, что то же самое сможет делать сам процесс. Улавливаете логику? Читайте про обработку сигналов.

anonymous
()
Ответ на: комментарий от Silverj

> http://www.ibm.com/developerworks/linux/library/l-cppexcep.html

Честно говоря, всё читать лень - просто пробежался по коду... И что? показано как ловить исключения в C++, дальше-то что? Можно в обработчике перед смертью назвать всех козлами а дальше?

anonymous
()
Ответ на: комментарий от anonymous

И, кстати, если мне не изменяет память - что бы вы не делали в обработчике SIGSEGV, ядро потом всё равно пришибёт процесс (вызовет стандартный обработчик)... но это вы лучше проверьте,,,

anonymous
()
Ответ на: комментарий от anonymous

> Честно говоря, всё читать лень - просто пробежался по коду... И что? показано как ловить исключения в C++, дальше-то что? Можно в обработчике перед смертью назвать всех козлами а дальше?

Ладно. Тема закрыта. Не буду отнимать у вас время.

Silverj
() автор топика

2 аффтар

По твоей ссылке описана C++-ная приблуда для выкидывания exception'а при получении сигнала. Понятно, что отловить сигнал можно.

Но единственное, что ты можешь корректно сделать в этом обработчике - выругаться и помереть, ибо сказано:

>The behavior of a process is undefined after it returns normally from a signal-catching function for a SIGBUS, SIGFPE, SIGILL, or SIGSEGV signal that was not generated by kill(), sigqueue(), or raise().

http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html

Сдохший процесс не тянет за собой подыхание родительского процесса, поэтому непонятно, зачем твоей "запускалке" это все нужно.

Ядро тут не при чем, ибо это не процесс в юзерспейсе.

anonymous
()
Ответ на: комментарий от Silverj

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

Именно с этого и надо было начинать.

Оформи то, что падает, в отдельный процесс. man 2 fork, man 2 execve, man 2 wait. Упав, задача удалится сама.

alexsaa
()

>Пишу программу на C++ в Linux. Необходимо обрабатывать исключения типа выход за область памяти, причем не падая с сообщением Segmentation Fault.

1) SEGFAULT относится к неперехватываемым сигналам. 2) Ввиду ублюдочности исклбчений в С++ лучше делать *((int*)0) = 0 чем кидать экзепшен. Так хотябы останется нормальный трупик для вивисекции. Для небольших ошибок лучше использовать коды возврата.

Absurd ★★★
()
Ответ на: комментарий от Absurd

> 1) SEGFAULT относится к неперехватываемым сигналам.

1. такого сигнала нет
2. SIGSEGV перехватываем

rei3er
()
Ответ на: комментарий от anonymous

> Но единственное, что ты можешь корректно сделать в этом обработчике - > выругаться и помереть, ибо сказано:

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

что касается применений таких сигналов, как SIGFPE, SIGILL и т. д
то, например, SIGILL запросто может использоваться для эмуляции неподдерживаемых CPU расширений типа SSEx и т. д

rei3er
()

Вот к этому вопросу:

> Но что делать дальше с приложением чтобы оно восстановило работу?

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

tailgunner ★★★★★
()

можно прочитать про надёжность программного обеспечения

дело, то всё в том, что возникновение ошибки и время её обнаружения могут отличаться...

ошибка была в начале, а краш случится через полчаса расчётов...

dimon555 ★★★★★
()

//Вот когда вот так что-то делал (правда для Си)

jmp_buf jmpbuf;

void sighandler(int signum)
{
    fprintf(stdout, "[%d]: %s %s(): signal = %d\n", 
            (int)getpid(), __FILE__, __FUNCTION__, signum);
    longjmp(jmpbuf, 1);
}

//---------------------------------------------------------------------------

int init( int val )
{
    pid_t pid = getpid();
    
    if(setjmp(jmpbuf) != 0) {
        cleanup();
        exit(0);
    }

    signal( SIGSEGV, sighandler );
    
    fprintf(stdout, "[%d] %s, %d %s().\n", 
               (int)pid, __FILE__, __LINE__, __FUNCTION__);        
    
    return 0;
}

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <dlfcn.h>
#include <signal.h>
#include <setjmp.h>
#include <sys/types.h>

int main(int argc, char *argv[])
{
    init((int)getpid());

    //Illegal instruction
    int *x = NULL;   x[0] = 55;
    
    cleanup();
    
    return 0;
} 

// В общем смотри в направлении jmp_buf jmpbuf;

karak
()
Ответ на: комментарий от karak

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

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

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

Let the dead take care of their dead

dilmah ★★★★★
()
Ответ на: комментарий от tailgunner

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

Полностью согласен, этот код не использован в жизни, а просто любопытство как эта шняга работает.

karak
()
Ответ на: комментарий от alexsaa

> Оформи то, что падает, в отдельный процесс

google software watchdog

anonymous
()
Ответ на: комментарий от tailgunner

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

Ну не всегда это идиотизм. Просто не всегда можно прервать работу приложения. Ведь программа может управлять каким то важным объектом и перезапуск оставит все без контроля. Что тогда делать? А так, та часть которая вызвала сбой пометится как аварийная и больше исполняться не будет.

Silverj
() автор топика
Ответ на: комментарий от Silverj

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

> Ну не всегда это идиотизм.

Всегда.

> Ведь программа может управлять каким то важным объектом и перезапуск оставит все без контроля.

А не-перезапуск оставит в работе программу, которая потенциально выдает неправильные управляющие данные, или вообще их не выдает (постоянный SIGSEGV и 100% времени в обработчике сигнала).

> Что тогда делать?

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

> А так, та часть которая вызвала сбой пометится как аварийная и больше исполняться не будет.

Только что говорилось о том, что "программа может управлять каким то важным объектом", а сейчас предлагается перманентно вывести часть программы из работы? Не вижу логики. Да и не имеет смысла такая реакция в программе на Си. И даже на Яве, наверное, не имеет.

tailgunner ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.