【问题标题】:How to clean up local data in SIGINT handler如何在 SIGINT 处理程序中清理本地数据
【发布时间】:2016-06-04 14:04:37
【问题描述】:

我需要在 SIGINT 处理程序中执行清理函数,但我无法将本地数据传递给它。举个例子:

int main(int argc, char *argv[]) {

    struct database *db = db_cursor();
    sockfd_t master_socket = init_server();

    signal(SIGINT, sigint_handler);

    while (1) {
        // accepting connections
    }
}

void sigint_handler(int s) {
    destroy_db(db);
    shutdown(master_socket, SHUT_RDWR);
    close(master_socket);
    exit(EXIT_SUCCESS);
}

如何实现这种行为?我试过让这个变量是全局的,但是 我无法在编译时调用此函数(错误:初始化元素不是编译时常量)。

【问题讨论】:

  • 您不应该在处理程序本身中执行所有这些逻辑。只需让它设置一个标志,并在主循环中测试该标志。
  • 加上 Oliver 的评论:输入标志 sig_atomic_t
  • 现在它可以工作了,但是我有像accept 这样的阻塞调用,当我调用SIGINT 时它不会立即停止。我应该使用多路复用来解决这个问题吗?
  • 如果accept() 没有返回,请使用sigaction() 而不是signal() 创建此信号处理程序,并取消设置传递结构的成员SA_RESTART 中的SA_RESTART 标志。
  • 您不需要在accept()上阻塞:只需将监听套接字设置为非阻塞,将其添加到select()ed(或polled)集合中,并在选择时检查标志() 返回 -1/EINTR。

标签: c signals blocking sigint


【解决方案1】:

只有非常有限数量的函数可以保证是异步信号安全的,因此可以从信号处理程序exit() f.e. 中调用。不属于他们。

采取不同的方法:

#include <signal.h>

volatile sig_atomic_t sigint_received = 0; /* volatile might be necessary depending on 
                                              the system/implementation in use. 
                                              (see "C11 draft standard n1570: 5.1.2.3")*/

void sigint_handler(int s) 
{
  sigint_received = 1;
}

int main(void) 
{
  signal(SIGINT, sigint_handler);

  while (!sigint_received) 
  {
    /* Do stuff. */
  }

  /* Clean up here. */
}

有关更多信息,请参阅


注意:为了最大限度地便携,您希望使用 sigaction() 而不是 signal()

替换signal() 的代码可能如下所示:

struct sigaction sa = 
{
  sigint_handler
  /*, SA_RESTART */ /* Set this by if blocking calls like read() or accept() 
                       should _not_ return on signal reception. */
};

if (-1 == sigaction(SIGINT, &sa, NULL))
{
  perror("sigaction() failed");
  exit(EXIT_FAILURE);
}

sigaction() 上的文档:

【讨论】:

  • volatile sig_atomic_t.
  • 没有。为什么你认为这是必要的? @EOF
  • 信号处理是通过操作系统进程完成的。没有外部设备在这里改变任何东西。
  • C11 标准草案 n1570:5.1.2.3 程序执行 5 当抽象机的处理因接收到信号而中断时,既不是无锁原子对象也不是无锁原子对象的对象的值volatile sig_atomic_t 类型的未指定,浮点环境的状态也是如此。当处理程序退出时,处理程序修改的任何对象(既不是无锁原子对象也不是 volatile sig_atomic_t 类型)的值变得不确定,如果浮点环境的状态被处理程序修改并且未恢复,则它的状态也是不确定的恢复到原来的状态。
  • @EOF 嗯,很公平,从引用的标准部分来看,似乎需要将sig_atomic_t 限定为volatile,具体取决于实现。 (标准的其他部分(7.14/2)没有那么明确。)
猜你喜欢
  • 2011-06-16
  • 2013-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-18
  • 2013-03-02
  • 1970-01-01
相关资源
最近更新 更多