Linux C 捕获终止信号以实现优雅终止

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7376228/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 06:08:39  来源:igfitidea点击:

Linux C catching kill signal for graceful termination

clinuxkill

提问by user623879

I have a process using sockets, database connections and the likes. It is basically a server process relaying between sensor data and a web interface, and as such it is important to ensure the application, if killed, terminates gracefully.

我有一个使用套接字、数据库连接等的进程。它基本上是一个在传感器数据和 Web 界面之间中继的服务器进程,因此确保应用程序(如果被终止)正常终止很重要。

How do I handle unexpected exceptions such as segfaults (at least for debugging) as well as kill signals so that I can close any connections and stop any threads running so that the process does not leave a mess of anything it is using?

我如何处理意外异常,例如段错误(至少用于调试)以及终止信号,以便我可以关闭任何连接并停止任何线程运行,以便进程不会留下任何正在使用的东西?

采纳答案by Soren

You install signal handlers to catch signals -- however in 99% of cases you just want to exit and let the Linux OS take care of the cleanup -- it will happily close all files, sockets, free memory and shutdown threads.

您安装信号处理程序来捕获信号——但是在 99% 的情况下,您只想退出并让 Linux 操作系统负责清理——它会很高兴地关闭所有文件、套接字、空闲内存和关闭线程。

So unless there is anything specifically you want to do, like sending a message on the sockets, then you should just exit from the process and not try to catch the signal.

因此,除非您有特别想做的事情,例如在套接字上发送消息,否则您应该退出进程而不是尝试捕获信号。

回答by daniel

I sometimes like to get a backtrace on SIGSEGV, the catching part goes like:

我有时喜欢在 SIGSEGV 上进行回溯,捕获部分如下:

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

void sig_handler(int);

int main() {
    signal(SIGSEGV, sig_handler);
    int *p = NULL;
    return *p;
}

void sig_handler(int sig) {
    switch (sig) {
    case SIGSEGV:
        fprintf(stderr, "give out a backtrace or something...\n");
        abort();
    default:
        fprintf(stderr, "wasn't expecting that!\n");
        abort();
    }
}

You do want to be very careful handling these things, e.g. make sure you can't trigger another signal.

您确实需要非常小心地处理这些事情,例如确保您不能触发另一个信号。

回答by Dietrich Epp

Catching signals is hard. You have to be careful. Your first step is to use sigactionto install a signal handler for the desired signals.

捕捉信号很难。你必须要小心。您的第一步是使用sigaction为所需信号安装信号处理程序。

  • Choose a set of signals to respond to and choose what they mean for your process. For example, SIGTERMquits, SIGHUPrestarts, SIGUSR1reloads configuration, etc.

  • Don't try to respond to all signals and don't try to "clean up" after signal that indicates an error in your program. SIGKILLcan't be caught. SIGSEGV, SIGBUS, and others like them shouldn't be caught unless you have a VERY good reason. If you want to debug, then raise the ulimit for core dumps — attaching a debugger to a core image is far more effective than anything you or I could ever code up. (If you do try to clean up after a SIGSEGVor something like that, realize that the cleanup code might cause an additional SIGSEGVand things could get bad quickly. Just avoid the whole mess and let SIGSEGVterminate your program.)

  • How you handle the signals is tricky. If your application has a main loop (e.g., selector poll) then the signal handler can just set a flag or write a byte to a special pipe to signal the main loop to quit. You can also use siglongjmpto jump out of a signal handler, but this is VERY difficult to get right and usually not what you want.

  • 选择一组要响应的信号并选择它们对您的过程的意义。例如,SIGTERM退出、SIGHUP重新启动、SIGUSR1重新加载配置等。

  • 不要尝试响应所有信号,也不要尝试在指示程序错误的信号之后“清理”。 SIGKILL不能被抓住。 SIGSEGV, SIGBUS, 和其他类似的人不应该被抓住,除非你有很好的理由。如果你想调试,那么提高核心转储的 ulimit - 将调试器附加到核心映像比你或我编码的任何东西都有效。(如果您确实尝试在 aSIGSEGV或类似的事情之后进行清理,请意识到清理代码可能会导致额外的SIGSEGV事情并且事情可能会很快变坏。只要避免整个混乱并让我们SIGSEGV终止您的程序即可。)

  • 你如何处理信号很棘手。如果您的应用程序有一个主循环(例如,selectpoll),那么信号处理程序可以只设置一个标志或将一个字节写入一个特殊的管道,以通知主循环退出。您也可以使用siglongjmp跳出信号处理程序,但这很难做到正确,而且通常不是您想要的。

It's hard to recommend something without knowing how your application is structured and what it does.

如果不知道您的应用程序的结构和作用,就很难推荐一些东西。

Also remember that the signal handler itself should do almost nothing. Many functions are not safe to call from signal handlers.

还要记住,信号处理程序本身几乎什么都不做。许多函数从信号处理程序调用是不安全的。