我有一个命令行应用程序。我面临的问题是,有时该应用程序的用户直接关闭运行我们的应用程序的终端,也使用以下命令:
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
答案 0 :(得分:1)
无论操作系统如何,SIGKILL
(即信号-9
)都由内核直接处理,并且在任何用户空间处理程序有机会处理任何内容之前,进程将被终止。 Linux内核就像Solaris Solaris一样。
目标进程无法保护自己免受该信号的攻击(在发送方或内核中拦截它之外)。
另一方面,关闭终端仿真器窗口会向其发送XEvent。在退出之前,终端仿真器应该向您的进程发送一个SIGHUP信号。
我建议在Solaris 10计算机上使用dtrace来调查此过程。从此脚本开始,显示发送的所有信号:http://www.brendangregg.com/DTrace/kill.d