为同一信号设置多个信号处理程序是否有效?

时间:2013-06-14 07:06:00

标签: c linux signals

我有两个链接到我的测试应用程序的共享库。这两个库都有SIGINT的信号处理程序。

对于相同的信号有多个信号处理程序是否有效?当我生成SIGINT信号时,处理程序将执行哪个顺序?

5 个答案:

答案 0 :(得分:18)

正如其他人所说,只能设置一个信号处理程序,这是最后一个。然后,您必须自己管理调用两个函数。 sigaction函数可以返回先前安装的信号处理程序,您可以自己调用它。

像这样(未经测试的代码):

/* other signal handlers */
static void (*lib1_sighandler)(int) = NULL;
static void (*lib2_sighandler)(int) = NULL;

static void aggregate_handler(int signum)
{
    /* your own cleanup */
    if (lib1_sighandler)
        lib1_sighandler(signum);
    if (lib2_sighandler)
        lib2_sighandler(signum);
}

... (later in main)
struct sigaction sa;
struct sigaction old;

lib1_init(...);
/* retrieve lib1's sig handler */
sigaction(SIGINT, NULL, &old);
lib1_sighandler = old.sa_handler;

lib2_init(...);
/* retrieve lib2's sig handler */
sigaction(SIGINT, NULL, &old);
lib2_sighandler = old.sa_handler;

/* set our own sig handler */
memset(&sa, 0, sizeof(sa));
sa.sa_handler = aggregate_handler;
sigemptyset(&sa.sa_mask);
sigaction(SIGINT, &sa, NULL);

答案 1 :(得分:7)

每个信号只能安装一个信号处理程序。只有最新安装的处理程序才会处于活动状态。

答案 2 :(得分:2)

我们可以用单信号处理器处理多个信号但是 但它不可能有相同信号的多个信号处理程序。

void sig_handler(int signo)
{
if (signo == SIGINT)
printf("received SIGINT 1\n"); 
}
void sig(int signo)
{
     if (signo == SIGINT)
        printf("received SIGINT 2\n");
}
   int main(void)
  {
      if(signal(SIGINT, sig_handler) == SIG_ERR)
          printf("\ncan't catch SIGINT\n");

      if (signal(SIGINT, sig) == SIG_ERR)
          printf("\ncan't catch SIGINT\n");
  // A long long wait so that we can easily issue a signal to this process
     while(1) 
       sleep(1);
     return 0;
  }

如果您尝试运行此代码,您将发现为该信号设置了最后分配的信号处理程序。 我认为不可能有相同信号的多信号处理程序。

答案 3 :(得分:1)

正如您在sigaction的手册页中看到的那样,新的信号处理程序将替换旧的信号处理程序,并返回旧的信号处理程序。

如果您有两个未使用的信号(例如SIGUSR1SIGUSR2),请将这些信号分配给SIGINT的两个信号处理程序。然后您可以为SIGINT编写自己的信号处理程序,然后您可以根据需要提高所需的未使用信号。

答案 4 :(得分:1)

沙巴兹击中了头上的钉子。但是,如果您正在寻找所有库可以使用的东西(前提是您可以访问源代码),您可以按照以下方式执行操作:

linked_list* sigint_handlers = NULL;

void sighand_init(sighand_config_t* config) {
    struct sigaction action;
    memset(&signalaction, 0, sizeof(signalaction));
    action.sa_handler = &sighand_main;

    // Order is important, in case we get a signal during start-up
    sigint_handlers = linked_list_new();
    sigaction(SIGINT, &action);
}

void sighand_main(int signum) {
    if (signum == SIGINT) {
        linked_list_node* node = linked_list_head(sigint_handlers);
        while ((node = node->next) != NULL) {
            node->object(signum);
        }
        if (sighand_config.exitonint) {
            app_exit(0);
        }
    }
}

void sighand_add_int_handler(void (*handler)(int)) {
    if (handler == NULL) return;
    linked_list_add(sigint_handlers, handler);
}

void sighand_destroy() {
    ...
    linked_list_destroy(signint_handlers);
    ...
}

或者,您可以自己使用它,并在加载每个库后,获取处理程序,然后调用add_handler。有点像:

loadlibrary(lib1.so);
sigaction1 = signalget(SIGINT);

loadlibrary(lib2.so);
sigaction2 = signalget(SIGINT);

sighand_init(...);
sighand_add_int_handler(sigaction1.sa_handler);
sighand_add_int_handler(sigaction2.sa_handler);

只是一些想法, 安东尼