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



我已经将产生问题的大量光纤调度器代码缩减为以下几行:
我所期望的是每次都干净地返回上下文,传递给处理程序。
我得到的是"汉德勒"打印三次,然后出现分段错误。

#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

至此,我自己对这个问题的研究可以提供部分答案。

首先,我找到了这篇文章,它是旧的,没有引用任何官方的信息来源: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的部分,我将不胜感激。

其次,在与一位大学讲师交谈后,我开始理解从信号处理程序中设置/交换上下文并不像在其他情况下那样直接。遗憾的是,向我解释这一点的人当时无法提供进一步的细节。

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

相关内容

  • 没有找到相关文章

最新更新