2012-04-03 36 views
1

我有一个小程序打开一个文件并对其执行一些操作。我订阅的文件关闭该程序终止如下:on_exit和CTRL + C

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); 

    ... 
} 

尝试执行此我注意到,它工作正常只有当程序正常终止。如果是CTRL + CSIGINTexit_handler回调未执行。

这不是很奇怪吗?我应该将exit(EXIT_FAILURE)呼叫与SIGTERM的信号处理程序联系起来吗?这种情况下的最佳做法是什么?

+1

请注意,在大多数TTY上,默认情况下,CTRL + C会将'SIGINT'发送到前台进程,而不是'SIGTERM'。 – 2016-03-22 18:30:02

+0

@JonathonReinhart正确。我修好了,谢谢。 – Dacav 2016-03-26 06:33:22

回答

4

首先,on_exit不是POSIX指定的(atexit与相同的语义是)。其次,在linux手册说:

的ON_EXIT()函数注册给定的功能,以在正常过程终止称为 ,是否经由出口(3),或通过从 回报程序的main()。

由信号被杀是不是一个过程,以便用on_exitatexit安装回调不隐式调用一个正常的退出。

+0

POSIX评论的好处。 – Dacav 2012-04-03 13:39:33

+0

实际上'atexit'是由ISO C标准定义的,所以它甚至在非POSIX实现中都存在。 – 2015-09-16 01:50:13

3

on_exit将不会被调用SIGTERM信号。你需要为它添加一个处理程序signal。例如:

void signalHandler(void) 
{ 
    ... 
} 

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

还要注意的是SIGKILL无法通过设计来抓住。

+0

'signalHandler'在这里可以简单地'exit(0)',它将调用'atexit'处理程序。 – 2016-03-22 18:28:09

2

on_exitman page

的ON_EXIT()函数注册给定的函数在 正常进程终止被调用,无论是通过出口经由来自返回(3)或 程序的main()。

所以,你需要明确地从signal.h

东西挂钩使用特定功能SIGTERM处理程序上的

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) 
{ 
... 
} 
2

号线,实际上你想要什么是不可能的。由Ctrl + C生成的信号是异步,这意味着它可能发生在程序中的任何两个机器指令之间,具体取决于何时按下Ctrl + C。因此,除非您的程序彻底避免在主程序流中的任何位置调用异步信号 - 不安全函数,否则从信号处理程序调用异步信号不安全函数是非法的。 exit是异步信号不安全的,就像它的大部分默认清理活动一样(如刷新/关闭打开的文件)。我期望atexit函数,你想注册(atexit,而不是on_exit,是这个函数的正确名称)也将要做异步信号不安全的事情。

如果您需要进行清理退出基于信号的情况下,你需要安装不exit本身的信号处理,而是设置一个全球性的挥发性标志,你的主要程序流程将在稍后检查(和exit如果它是真正)。