【发布时间】:2014-10-18 19:40:51
【问题描述】:
我有一个命令行应用程序。我面临的问题是,有时该应用程序的用户也会使用以下命令直接关闭运行我们的应用程序的终端:
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 命令并记下与之关联的标准输入文件的名称时,然后在同一终端中输入 bash 命令时,如果我记下标准输入文件,则再次输入使用 tty 命令与之关联,我发现两个 bash shell,一个在我启动终端时默认打开,另一个是我通过在 bash 控制台中键入 bash 命令手动打开的,共享相同的标准输入文件名。
因此,当我杀死作为我的进程的父进程的第二个 bash 时,与之关联的标准输入文件不会被关闭,我认为这就是我没有收到 SIGHUP 信号的原因。
当它的控制控制台被杀死时,我可以使用任何其他方法来过于优雅地杀死我的进程。
使用的终端模拟器:GNOME Terminal 2.31.3 默认外壳:bash
【问题讨论】:
-
你使用哪个外壳?
-
我在 tcsh 和 bash 中试过
-
由于信号 9 不可捕获,您的终端没有机会进行任何清理,这将是它为子进程生成 HUP 的地方。您需要重新教育您的用户不要使用
kill -9。可能采取极端措施...... -
通过窗口管理器装饰杀死一个窗口可能会发送 SIGTERM 而不是 SIGHUP,但这可能会根据您使用的 GUI(甚至可能在单个 GUI 的不同版本中)而有所不同。无论如何,SIGKILL (a.k.a
kill -9) 应该只在用尽其他可能性后很少使用。 -
@mSatyam 您的进程可以定期检查其 PPID(父 PID)并根据其更改(变为“1”)采取行动,这意味着父进程死亡/崩溃/等等。
标签: c linux unix signals solaris