Ошибка сегментации при использовании linux create_timer и sigaction API

Я пытаюсь интегрировать следующий фрагмент кода в более крупную программу (которой, к сожалению, я не могу поделиться), которая работает в системе ARM‹-> DSP:

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <time.h>

#define CLOCKID CLOCK_REALTIME
#define SIG SIGUSR1

timer_t timerid;

int i = 0;
int sec = 0;

volatile int keep_going = 1;

clock_t curr_time = 0, t_old = 0;

static void handler(int sig)
{
    curr_time = clock();
    if ((curr_time - t_old)/CLOCKS_PER_SEC >= 10.)
    keep_going = 0;
}

int main(int argc, char *argv[])
{
    struct sigevent sev;
    struct itimerspec its;
    long long freq_nanosecs;
    sigset_t mask;
    struct sigaction sa;
    memset(&sa, 0, sizeof sa);

    // Timer settings
    printf("Establishing handler for signal %d\n", SIG);
    sa.sa_flags = SA_SIGINFO;
    sa.sa_handler = handler;
    sigemptyset(&sa.sa_mask);
    sigaction(SIG, &sa, NULL);

    sev.sigev_notify = SIGEV_SIGNAL;
    sev.sigev_signo = SIG;
    sev.sigev_value.sival_ptr = &timerid;
    timer_create(CLOCKID, &sev, &timerid);

    /* Start the timer */
    its.it_value.tv_sec = 0;
    its.it_value.tv_nsec = 1000;
    its.it_interval.tv_sec = its.it_value.tv_sec;
    its.it_interval.tv_nsec = its.it_value.tv_nsec;

    timer_settime(timerid, 0, &its, NULL);
    t_old = clock();
    while(keep_going);
    printf("%f sec passed..\n", (double)(curr_time - t_old)/CLOCKS_PER_SEC);
    exit(EXIT_SUCCESS);
}

Как видите, это очень простой код, и при его отдельном запуске в системе он отлично работает. Цикл while предназначен только для демонстрации и может быть проигнорирован. Шаги обработчика и инициализации одинаковы.

Проблемы начались, когда я попытался интегрировать его с более крупной программой. Внезапно я получаю ошибку сегментации, если устанавливаю интервал таймера менее 10 мс.

Я попытался сократить операции в обработчике до простой строки 'curr_time = 0', думая, что это может иметь какое-то отношение к операциям с плавающей запятой в обработчике, но это не помогло.

Следует отметить, что я использую API выделения непрерывной памяти для буферов разделяемой памяти ARM‹->DSP, хотя я сомневаюсь, что это как-то связано с этим, поскольку я не выделяю новую память в обработчике.

Итак, кто-нибудь знает о возможных причинах ошибки сегментации?


person ytm    schedule 23.08.2015    source источник
comment
clock() не является асинхронным. Кроме того, переменная, изменяемая в обработчике сигналов (keep_going), должна быть атомарной или иметь тип volatile sig_atomic_t.   -  person EOF    schedule 23.08.2015
comment
Кроме того, man sigaction: [...]If SA_SIGINFO is specified in sa_flags, then sa_sigaction (instead of sa_handler) specifies the signal-handling function for signum. This function receives the signal number as its first argument, a pointer to a siginfo_t as its second argument and a pointer to a ucontext_t (cast to void *) as its third argument.[...].   -  person EOF    schedule 23.08.2015
comment
Спасибо. Теперь я присвоил правильные значения в соответствии с определенными на странице руководства sigaction. Это не решило проблему, но могло быть похоже на нее, если бы я не исправил это. В любом случае, похоже, проблема была в том, что я запустил таймер перед критическим разделом инициализации.   -  person ytm    schedule 24.08.2015


Ответы (1)


всегда полезен SEGFAULT, это дамп ядра:

$ ulimit -c unlimited

Теперь запустите ваше приложение, после segfault в вашем текущем каталоге должен быть «основной» файл.

Теперь используйте GDB для дампа:

gdb <executable> -c <core-file>

теперь вы можете видеть, где у вас есть segfault. Если у вас многопоточное приложение, напишите эту строку в gdb-console

$ gdb thread apply all bt
person arash javanmard    schedule 23.08.2015
comment
Спасибо, как я писал в посте выше, мне в итоге удалось решить проблему. Однако сейчас есть новый, но это выходит за рамки моего первоначального вопроса. - person ytm; 24.08.2015