LINUX.ORG.RU

Как отловить и обработать ошибку возникающую в разделяемой библиотеке?


0

0

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

P.S. прога пишется на чистом Си. С++ не предлагать. P.S. мне предлагали это осуществить это с помощью асмовских вставок, но я в нем не варю. может кто предложит конкретный код.



Последнее исправление: Puld (всего исправлений: 2)

В C/C++ это далеко не всегда в принципе возможно. Как вариант - вынести взаимодействие с «потенциально кривыми» библиотеками в отдельный процесс.

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

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

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

Решение «в лоб»: навесить обработчики сигналов и перед вызовом каждой сторонней ф-и сохранять контекст. Только непонятно зачем тебе внешняя библиотека, если программа может работать и без нее.

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

дело в том что эти библиотеки являются драйверами устройств ввода/вывода а программа - менеджером ввода/вывода. функционал драйвера вынесен в библиотечку для расширяемости.

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

>НО основная программа должна продолжать работу!

man sigsetjmp, man siglongjmp

Но тут надо четко осознавать, что выделенные ресурсы освободить будет некому.

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

>man sigsetjmp, man siglongjmp

для меня это как мартышке очки... подскажите, как пользоваться этими функциями (sigsetjmp, siglongjmp)? плиз! желательно на примере:)

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

Значит у тебя нет тредов. Замени вызовы pthread_getspecific на обыкновенную глобальную переменную. pthread_setspecific, как я понимаю, все равно вызывать некому.

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

у автора просто каша в голове, хоть решение и красивое. в C ни когда не было try-catch! это он с C++ путает. но от куда же это знать виндусятнику?

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

слегка подрихтовал первый вариант из вышеуказанного источника

/* gcc -Wal -o try try.c -lpthread */

#include <pthread.h>
#include <signal.h>
#include <setjmp.h>
#include <stdio.h>

#define try { sigjmp_buf buf; pthread_setspecific(jmp_key, &buf); if(!sigsetjmp(buf, 1))
#define catch else
#define final pthread_setspecific(jmp_key, 0); }

pthread_key_t jmp_key;

void
handler(int sig)
{
        sigjmp_buf *ref;

        ref = pthread_getspecific(jmp_key);
        if (ref)
                siglongjmp(*ref, 1);
}

void
init_try()
{
        struct sigaction sa;

        sigemptyset(&sa.sa_mask);
        sa.sa_flags = 0;
        sa.sa_handler = handler;
        sigaction(SIGFPE, &sa, 0);
        sigaction(SIGSEGV, &sa, 0);

        pthread_key_create(&jmp_key, 0);
}

void   *
thread_a(void *notused)
{
        int     n;

        try {
                n = 1;
                n = n * 0;
                n = 1 / n;
        } catch {
                printf("error thread1\n\a");
        } final 

        return NULL;
}


void   *
thread_b(void *notused)
{
        int     n;
        char    c;

        try {
                for (n = 0;; n++)
                        c = ((char *) &n)[n];
        } catch {
                printf("error thread2\n\a");
        } final

        return NULL;
}

int
main()  
{
        pthread_t id;

        init_try();

        pthread_create(&id, NULL, thread_a, NULL);
        pthread_join(id, NULL);

        pthread_create(&id, NULL, thread_b, NULL);
        pthread_join(id, NULL);

        return 0;
}
а то у меня тоже есть друг-виндусятник, считающий, что раз Visual Studio и C и C++ компилирует, то C — это диалект C++ и вообще всё это один язык. и хоть влоб, хоть полбу! :(

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

огромное СПАСИБО! поклон до земли! вы развеяли все туманные мифы о том что в чистом си нет ничего подобного try...catch.

Собирай с -lpthread

да, вот про это забыл. спасибо!

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

под оффтопом делается через:
SetUnhandledExceptionFilter

под линухом уже объяснили

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

второй вариант из вышеуказанного источника тоже работает, нужно только заменить

static bool ok=true; > > > static int ok=1;

ok=false; > > > ok=0;

всем спасибо! тема закрыта:)

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

Я хорошо различаю))) Просто чистый си я так и не думал упоминать, да писать как-то не очень на нём хочу.

А вам проще три строки с bool убрать и вообще потоки убрать. Это ближе к делу; и соберется в голую.

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

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

а если не чистый C, то какой же прок в этом упражнении? в C++ try/catch «из коробки» и изобретать то, что и так уже есть на уровне языка по-моему просто безсмысленно.

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

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

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