7

我已将产生问题的巨大光纤调度程序代码减少到以下几行。
我期望的是每次都干净地返回上下文,传递给处理程序。
我得到的是“处理程序”。打印了三遍,然后是分段错误。

#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。

4

1 回答 1

1

在这一点上,我自己对该问题的研究可以作为部分答案。

首先,我发现这篇文章很旧,并且没有引用任何官方信息来源: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 的部分,将不胜感激。

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

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

于 2013-03-29T22:01:12.857 回答