我有一个命令行应用程序 . 我面临的问题是,有时该应用程序的用户直接关闭运行我们的应用程序的终端,也使用以下命令:
kill -9 pid_of_parent_console
在上述情况下,我们的应用程序应该通过执行所有必要的清理来优雅地关闭 . 为此,我编写了一个处理SIGHUP信号的信号处理程序,因为当控制进程的终端退出时,它将SIGHUP发送到在其下运行的进程,我们已经处理这些进程以优雅地退出我们的进程 . 但是,如果用户打开一个终端,假设是默认bash,然后他再次在其中键入bash命令然后运行我们的应用程序,如果假设杀死了打开终端后手动执行bash执行的应用程序父进程,那么我们的应用程序不会获得SIGHUP并且不会优雅地退出 . 为简单起见,我写了下面的代码重现了这个问题:
#include <stdio.h>
#include <signal.h>
FILE *fp = NULL;
int flag = 1;
void handler(int signum)
{
flag = 0;
}
int main()
{
signal(SIGHUP, handler);
// just for testing
fp = fopen("file", "w");
// loop terminates only when HUP is generated
while (flag);
// if SIGHUP is generated then code should reach here
// and write the below in file.
fprintf(fp, "SIGHUP Generated");
fclose(fp);
return 0;
}
为简单起见,我没有使用sigaction来处理信号 .
我观察到的是,当我打开一个终端并按下tty命令并记下与之关联的stdin文件的名称,然后在同一个终端中,如果我输入bash命令,如果我记下与之关联的stdin文件使用tty命令,我发现的是两个bash shell,一个在我启动终端时默认打开,一个我通过在bash控制台中键入bash命令手动打开共享相同的stdin文件名 .
因此,当我杀死第二个bash是我的进程的父进程时,与之关联的stdin文件没有被关闭,我认为这就是为什么我没有收到SIGHUP信号 .
有没有其他方法可以用来在控制台被杀死时过于优雅地杀死我的进程 .
使用的终端仿真器:GNOME终端2.31.3默认shell:bash
1 回答
无论操作系统如何,
SIGKILL
(即信号-9
)都由内核直接处理,并且在任何用户空间处理程序有机会处理任何内容之前,进程将被终止 . Linux内核就像Solaris内核一样 .然后,目标进程无法保护自己免受该信号的影响(在发送方或内核中拦截它之外) .
另一方面,关闭终端仿真器窗口会向其发送XEvent . 在退出之前,终端仿真器应该向您的进程发送一个SIGHUP信号 .
我建议在Solaris 10机器上使用dtrace来调查此过程 . 从这个脚本开始,显示发送的所有信号:http://www.brendangregg.com/DTrace/kill.d