使信号切换另一个信号的动作

时间:2013-11-11 18:02:36

标签: c signals libc

我在使用C语言。我试图抓住并处理两个不同的信号:

  • INT:捕获此信号时, action1 action2 被触发
  • 退出:当捕获到此信号时,切换INT信号操作( action1 - > action2 action2 - &gt; < EM>动作1 )

默认INT信号操作设置为 action1

在我的代码中, switchaction 函数很好地由QUIT信号触发,但对INT信号动作没有影响:s

#include <signal.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>

typedef void (*sighandler_t)(int);
sighandler_t prev_handler;

void action1(int n){
  printf("First message\n");
}
void action2(int n){
  printf("Second message\n");
}

void switchaction(int n){
  printf("Switch action\n");
  prev_handler=action2;
}

int main() {
  prev_handler = action1;
  printf("PID: %d\n", getpid());
  prev_handler= signal(SIGINT,prev_handler);
  signal(SIGQUIT,switchaction);

  travail(); //This function never ends
}

您是否知道我的代码中出了什么问题?

谢谢,

1 个答案:

答案 0 :(得分:2)

您的系统调用

prev_handler= signal(SIGINT,prev_handler);

在执行prev_handler系统调用时将信号处理程序设置为signal变量的值。更改{之后)prev_handler的值不会更改SIGINT信号的处理。换句话说,signal(和大多数C调用)具有call by value语义。如果你拨打signal一次,内核会保留相同的处理程序(直到你用相同的信号号码再次呼叫signal,或直到你拨打sigaction(2)等等......)。

仔细阅读(假设您使用的是Linux)signal(7)signal(2)手册页。

我会改为定义

volatile sig_atomic_t howhandle;

void switchaction(int n __attribute__((unused))) {
    if (howhandle) 
       howhandle = 0;
    else 
       howhandle = 1;
}

void handleint (int n) {
    if (howhandle) action1(n); else action2(n);
}

并安装

signal(SIGINT, handleint);
signal(SIGQUIT, switchaction);

另请注意,处理程序中调用printf不正确(因为printf 是异步信号安全函数,但是你在action1中调用它,由handleint调用...)。再读一遍signal(7)

您应该在volatile sig_atomic_t工作函数内的适当位置使用其他travail变量并测试(并清除它们),但只能在信号处理程序中设置它们。设置volatile sig_atomic_t变量几乎是你在信号处理程序中可靠地做的唯一事情。

如果您接受Linux特定解决方案,请详细了解signalfd(2)(并同时使用poll(2) ...)。另请阅读Advanced Linux Programming