【问题标题】:"kill -15" triggers the sigaction code but does not terminate my C program“kill -15”会触发 sigaction 代码,但不会终止我的 C 程序
【发布时间】:2013-06-02 17:06:48
【问题描述】:

我有一个用 C 开发的程序。我在这个程序中添加了一个 sigaction 处理程序,以便在退出程序之前执行一些 C 代码:

void signal_term_handler(int sig)
{
    printf("EXIT :TERM signal Received!\n");
    int rc = flock(pid_file, LOCK_UN | LOCK_NB);
    if(rc) {
        char *piderr = "PID file unlock failed!";
        fprintf(stderr, "%s\n", piderr);
        printf(piderr);
    }
    exit(EXIT_SUCCESS);
}

int main(int argc, char **argv)
{
    struct sigaction sigint_action;

    sigint_action.sa_handler = &signal_term_handler;
    sigemptyset(&sigint_action.sa_mask);

    sigint_action.sa_flags = SA_RESETHAND;
    sigaction(SIGTERM, &sigint_action, NULL);
        ...........
}

注意:我的程序包含 2 个正在运行的子线程

当我执行 myprogram 然后我调用 kill -15 <pidnumber> 来杀死我的程序。我在标准输出中收到消息"EXIT :TERM signal Received!\n",但程序没有退出。

我的 sigaction 代码中是否缺少某些内容?

【问题讨论】:

  • 如果您在信号处理程序中取出所有非法代码,您将留下if (rc) { char* piderr = "..."; }

标签: c linux signals kill


【解决方案1】:

exit() 不一定是异步信号安全的。

直接从信号处理程序调用_exit()abort() 结束进程。


flock()printf 系列函数的所有成员也不是异步信号保存。


有关异步信号安全功能的完整列表,您可能想click here

【讨论】:

  • 对于异步信号保存是否有 flock() 的替代品?如果没有,是否可以使其异步信号保存?
  • @MOHAMED:不,除了破解glibc 和/或操作系统的内核之外,我看不到制作flock() async-signal-save 的方法。但是,从您在SIGTERM 触发的事实来看,如果您有可能遇到 XY 问题的印象:要对程序终止执行任何操作,使用atexit() 安装退出处理程序将是合适的方法。
  • 下面topic中的答案使用atexit ()作为解决方案。我不确定建议的解决方案是一种节省的方法。你能确认这是否是一种保存方式吗?
  • @mohamed:您链接的方法将一无所获。
  • @mohamed:澄清一下:您的基地是否打算在流程结束时执行一些操作?
【解决方案2】:

我仍然怀疑你有一个 XY 问题,即试图在接收到 SIGTERM 时取消flock() 文件。

要实现这一点(并以此绕过只能在信号接收上使用异步信号安全功能的限制,请使用以下方法:

  • 在主线程中屏蔽所有要由应用处理的信号。
  • 创建一个线程。
  • 通过修改线程的信号掩码,使该线程接收所有要处理的信号。
  • 在此线程中循环 sigwaitinfo() 以接收和分派信号。
  • 然后根据该线程接收到的信号做需要做的事情,而不受任何限制,因为缺少任何功能的异步信号安全性。

【讨论】:

  • 感谢您的回答(+1)。作为解决方案很有趣,但我只想在退出之前解锁一个文件。所以与我想要的相比,添加这样的行为看起来很复杂
  • @MOHAMED:虽然看起来有点复杂,但它是以灵活且最安全的方式处理信号响应的唯一方法,尤其是在处理关机情况时。也是在多线程环境中处理信号的一种非常通用的方法。
  • @MOHAMED:注意当进程退出时锁会自动释放;死进程没有锁。
【解决方案3】:

这很可能是因为实际上不允许您在信号处理程序中做很多事情(而且调用库函数肯定是粗略的)。

处理这样的事情的正常方法是让信号处理程序设置一个变量或排队一个普通主循环将处理然后退出的事件。

【讨论】:

  • 更糟糕的是,flock 是一个系统调用。如果例程使用atexit 注册,exit 也可能会出现问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-01-18
  • 1970-01-01
  • 1970-01-01
  • 2017-12-15
  • 1970-01-01
  • 1970-01-01
  • 2017-04-06
相关资源
最近更新 更多