[英]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 + C (
SIGINT
),则不执行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_exit
和atexit
安装的回调。
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.