LINUX.ORG.RU

странное поведение сигнала SIGSEGV


0

1

привет.

в проге, создаю обработчик сигнала SIGSEGV, в котором запускается gdb и выводит backtrace.

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

подскажите, в чем может быть причина?

благодарен.

★★★

не очень ясно из описания, но при рекурсии имеем два эффекта: 1. если рекурсией исчерпан стек, то на каком стеке работать обработчику? Cм. SA_ONSTACK в man sigaction. 2. Если из обработчика, то сигнал временно получил default-поведение.

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

вот(http://www.unix.com/50305-post2.html) нашел описание своей ситуации, и там говорится про использование для обработчика альтернативного стека. но что это? как/где его получить?

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

Cм. SA_ONSTACK в man sigaction.

что-то я поначалу недоглядел это предложение. спасибо, ушел разбираться.

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

что-то не получается..

код установки обработчика:

static void set_signal_handler(int signum) {
	 struct sigaction new_action;
	 sigemptyset(&new_action.sa_mask);
	 new_action.sa_handler = signal_handler;
	 new_action.sa_flags = (signum == SIGUSR1) ? 0 : SA_RESETHAND|SA_ONSTACK;
	 if ( sigaction(signum, &new_action, 0) ) {
		  fprintf(stderr, "%s: %dn", "cant set handler for signal", errno);
	 }
}

niXman ★★★
() автор топика
Ответ на: комментарий от niXman
       #include <unistd.h>
       #include <signal.h>
       #include <stdio.h>
       #include <malloc.h>
       #include <stdlib.h>
       #include <errno.h>
       #include <sys/mman.h>

       #define handle_error(msg) \
           do { perror(msg); exit(EXIT_FAILURE); } while (0)

       char *buffer;

       static void
       handler(int sig, siginfo_t *si, void *unused)
       {
           printf("Got SIGSEGV at address: 0x%lx\n",
                   (long) si->si_addr);
           exit(EXIT_FAILURE);
       }

        void abzac(int i)
        {
                abzac(i+1);
        }

       int
       main(int argc, char *argv[])
       {
           char *p;
           int pagesize;
           struct sigaction sa;
           stack_t ss;

           ss.ss_sp = malloc(SIGSTKSZ);
           if (ss.ss_sp == NULL)
               /* Handle error */;
           ss.ss_size = SIGSTKSZ;
           ss.ss_flags = 0;
           if (sigaltstack(&ss, NULL) == -1)
               /* Handle error */;

           sa.sa_flags = SA_SIGINFO | SA_ONSTACK;
           sigemptyset(&sa.sa_mask);
           sa.sa_sigaction = handler;
           if (sigaction(SIGSEGV, &sa, NULL) == -1)
               handle_error("sigaction");

           abzac(1);
           exit(EXIT_SUCCESS);
       }

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

> что-то не получается.. в смысле, обработчик все равно не вызывается. идеи?

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

ааа, вот оно как. спасибо огромное! пробую...

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

да, все работает, спасибо еще раз!

вопрос тут возник: альтернативный стек может быть только один общий для всех обработчиков?

спасибо.

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

А для других обработчиков кроме SIGSEGV нет особого повода заказывать SA_ONSTACK. Но судя по описанию один на таску.

io ★★
()

создаю обработчик сигнала SIGSEGV, в котором запускается gdb и выводит backtrace.

Может разрешить сбрасывать coredump на диск?

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