使用带有SIG_INFO的sigaction处理程序的第三个参数(void * context)会导致分段错误

时间:2013-03-27 17:22:24

标签: c gcc signals handler ucontext

我已经减少了一个巨大的光纤调度程序代码,这个代码产生了以下几行的问题 我所期待的是每次都清楚地回到上下文,传递给处理程序 我得到的是“处理程序。”打印出三次,然后是分段错误。

#include <ucontext.h>
#include <signal.h>
#include <stdio.h>

ucontext_t currently_executed_context;

void handler_sigusr1(int signum, siginfo_t* siginfo, void* context)
{
    currently_executed_context = (*(ucontext_t*)context);

    printf("Handler. ");
    setcontext(&currently_executed_context);
}

int main()
{
    setbuf(stdout,0);

    struct sigaction action_handler;

    action_handler.sa_sigaction = handler_sigusr1;
    action_handler.sa_flags = SA_SIGINFO;

    sigaction(SIGUSR1,&action_handler,NULL);

    for(;;) { kill(getpid(),SIGUSR1); sleep(1); }

    return 0;
}

在两个不同的Linux发行版上使用gcc-4.4.3和gcc-4.4.5。

1 个答案:

答案 0 :(得分:1)

此时,我自己对问题的研究可以作为部分答案提供。

首先,我找到了this article,这是旧的,并没有引用任何官方信息来源:http://zwillow.blogspot.com/2007/04/linux-signal-handling-is-broken.html。这是一个相关的引文:

  

第二个问题:你不能使用setcontext()离开信号处理程序并跳转到另一个先前保存的上下文中。 (或者,就此而言,您无法使用它返回到作为参数传递给信号处理程序的相同上下文。)换句话说,信号处理程序如

static void sighandler(
   int signo, siginfo_t *psi, void *pv)
{
  memcpy(puc_old, pv, sizeof(ucontext_t));
  /* choose another context to dispatch */
  setcontext(puc_another);
}
     

不起作用。它不会恢复puc_other中指定的信号掩码,也不会重新建立备用信号堆栈等。但是,这种方案在Solaris上完美运行。

如果有人可以确认有关Solaris的部分,我们将不胜感激。

其次,在与大学讲师交谈之后,我逐渐明白,在信号处理程序中设置/交换上下文并不像在其他情况下那样直接。可悲的是,向我解释这个问题的人当时无法提供进一步的细节。

因此,我的两个来源似乎都不完全可靠,但仍然是线索。