简体   繁体   English

on_exit和CTRL + C

[英]on_exit and CTRL+C

I've got a small program that opens a file and does some operation on it. 我有一个小的程序,可以打开文件并对其进行一些操作。 I subscribed the file closure to the program termination as follows: 我将文件关闭订阅到程序终止,如下所示:

static
void exit_handler (int ev, void *arg)
{
    fprintf(stderr, "bye %d\n", WEXITSTATUS(ev));
    fclose((FILE *)arg);
}

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

    ...

    out = fopen(argv[1], "wt");
    if (out == NULL) {
        perror("Opening output file");
        exit(EXIT_FAILURE);
    }
    on_exit(exit_handler, out);

    ...
}

Trying to execute this I notice that it works properly only if the program terminates normally. 尝试执行此操作时,我注意到只有在程序正常终止时它才能正常运行。 In case of CTRL + C ( SIGINT ) the exit_handler callback is not executed. 如果使用CTRL + CSIGINT ),则不执行exit_handler回调。

Isn't that weird? 那不是很奇怪吗? Should I associate a exit(EXIT_FAILURE) call to the signal handler for SIGTERM ? 我应该将exit(EXIT_FAILURE)调用与SIGTERM的信号处理程序关联吗? What is the best practice in this case? 在这种情况下,最佳做法是什么?

First of all, on_exit isn't specified by POSIX ( atexit with the same semantics is). 首先,POSIX未指定on_exit (具有相同语义的atexit是)。 Second , the linux manual says: 其次,linux手册说:

The on_exit() function registers the given function to be called at normal process termination , whether via exit(3) or via return from the program's main(). on_exit()函数注册要在正常进程终止时调用的给定函数,无论是通过exit(3)还是通过程序main()的返回。

Getting killed by a signal is not a normal exit for a process so callbacks installed with on_exit and atexit aren't implicitly called. 被信号杀死不是进程的正常退出,因此不会隐式调用通过on_exitatexit安装的回调。

on_exit will not be invoked for SIGTERM signals. 对于SIGTERM信号,不会调用on_exit You need to add a handler for it with signal . 您需要使用signal添加一个处理程序。 For example: 例如:

void signalHandler(void)
{
  ...
}

int main(void)
{
  signal(SIGTERM, signalHandler);
}

Also note that SIGKILL can not be caught by design. 另请注意, SIGKILL不能被设计捕获。

No, and in fact what you want is impossible. 不,实际上您想要的是不可能的。 The signal generated by Ctrl+C is asynchronous , meaning it could occur between any two machine instructions in your program depending on when Ctrl+C is hit. Ctrl + C生成的信号是异步的 ,这意味着它可能会在程序中的任何两条机器指令之间发生,具体取决于何时按下Ctrl + C。 As such, unless your program is thoroughly avoiding calling async-signal-unsafe functions anywhere in the main program flow, it's illegal to call async-signal-unsafe functions from the signal handler. 因此,除非您的程序完全避免在主程序流中的任何位置调用异步信号不安全函数,否则从信号处理程序中调用异步信号不安全函数是非法的。 exit is async-signal-unsafe, as is most of the default cleanup activity it does (like flushing/closing open files). exit是异步信号不安全的,就像大多数默认清除活动一样(例如刷新/关闭打开的文件)。 I would expect the atexit function you want to register ( atexit , not on_exit , is the correct name for this function) is also going to want to do async-signal-unsafe things. 我希望您要注册的atexit函数( atexit ,不是on_exit ,是该函数的正确名称)也将要做异步信号不安全的事情。

If you need to perform cleanup when exiting based on a signal, you need to install a signal handler that does not exit itself, but instead sets a global volatile flag that your main program flow will later inspect (and exit if it's true). 如果您需要在退出时基于信号执行清除操作,则需要安装一个不会exit自身的信号处理程序,而是设置一个全局volatile标志,您的主程序流将在以后检查该标志(如果为真,则exit )。

From man page of on_exit , on_exit 手册页中,

The on_exit() function registers the given function to be called at normal process termination, whether via exit(3) or via return from the program's main(). on_exit()函数注册要在正常进程终止时调用的给定函数,无论是通过exit(3)还是通过程序main()的返回。

So you need to explicity hook up a handler for SIGTERM using specific functions from signal.h 因此,您需要使用signal.h中的特定函数来显式连接SIGTERM的处理程序。

Something on the lines of 一些东西

struct sigaction action;

memset (&action, 0, sizeof(action));
action.sa_handler = sigterm_handler;

if (sigaction(SIGTERM, &action, 0)) 
{
    perror ("sigaction");
    return 1;
}

/* SIGTERM handler. */
static void sigterm_handler (int sig)
{
...
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM