【问题标题】:Segmentation fault when using linux create_timer and sigaction API使用 linux create_timer 和 sigaction API 时出现分段错误
【发布时间】:2015-08-23 17:32:35
【问题描述】:

我正在尝试将以下代码集成到在 ARMDSP 系统上运行的更大程序(不幸的是,我无法共享):

#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',认为这可能与处理程序中的浮点操作有关,但没有帮助。

应该注意的是,我为 ARMDSP 共享内存缓冲区使用了连续内存分配 API,尽管我怀疑它与它有什么关系,因为我没有在处理程序中分配任何新内存。

那么,有人知道分段错误的可能原因吗?

【问题讨论】:

  • clock() 不是异步安全的。此外,在信号处理程序 (keep_going) 中修改的变量必须是原子的或类型为 volatile sig_atomic_t
  • 此外,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.[...].
  • 谢谢。我现在根据 sigaction 手册页中的定义分配了正确的值。它没有解决问题,但如果我没有解决这个问题,它可能会伪装成一个问题。无论如何,问题似乎在于我在关键初始化部分之前启动了计时器。

标签: c linux timer segmentation-fault sigaction


【解决方案1】:

SEGFAULT 总是有帮助的是核心转储:

$ ulimit -c unlimited

现在运行您的应用程序,在出现段错误后,您的当前目录中必须有一个“核心”文件。

现在使用 GDB 转储:

gdb <executable> -c <core-file>

你现在可以看到你在哪里遇到了段错误。 如果您有多线程应用程序,请在 gdb-console 中写入此行

$ gdb thread apply all bt

【讨论】:

  • 谢谢,正如我在上面的帖子中所写,我最终设法解决了这个问题。不过,现在有一个新的,但这超出了我最初的问题。
猜你喜欢
  • 2019-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-18
  • 2017-06-06
  • 2017-08-26
  • 2018-06-18
  • 2019-05-10
相关资源
最近更新 更多