首页 文章

Linux C捕获kill信号以便正常终止

提问于
浏览
14

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

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

3 回答

  • 9

    您安装信号处理程序以捕获信号 - 但是在99%的情况下您只想退出并让Linux操作系统负责清理 - 它将很乐意关闭所有文件,套接字,空闲内存和关闭线程 .

    因此,除非你想要做任何具体的事情,比如在套接字上发送消息,那么你应该退出进程而不是试图捕获信号 .

  • 7

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

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

    • Don 't try to respond to all signals and don' t在指示程序错误的信号后尝试"clean up" . SIGKILL 无法 grab . 除非你有充分的理由,否则不应该 grab SIGSEGVSIGBUS 和其他类似的人 . 如果你想调试,那么提高核心转储的ulimit - 将调试器附加到核心映像比你或我编写的任何代码都要有效得多 . (如果你确实尝试在_2651317之后进行清理或类似的事情,请认识到清理代码可能会导致额外的 SIGSEGV 并且事情可能会很快变坏 . 只要避免整个混乱,让 SIGSEGV 终止你的程序 . )

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

    在不知道应用程序的结构和功能的情况下,很难推荐一些东西 .

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

  • 12

    我有时喜欢在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();
        }
    }
    

    你确实要小心处理这些事情,例如:确保你不能触发另一个信号 .

相关问题