【问题标题】:Gracefully Terminating a process when its controlling shells gets killed当进程的控制 shell 被杀死时优雅地终止进程
【发布时间】: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


【解决方案1】:

无论操作系统如何,SIGKILL(即信号-9)都由内核直接处理,并且在任何用户态处理程序有机会处理任何内容之前,进程就被杀死了。 Linux 内核就像 Solaris 内核一样。

那么目标进程就没有办法保护自己免受该信号的影响(除了在发送方或内核中拦截它)。

另一方面,关闭终端仿真器窗口会向其发送 XEvent。在退出之前,终端模拟器可能应该向您的进程发送一个 SIGHUP 信号。

我建议在 Solaris 10 机器上使用 dtrace 来调查这个过程。从这个脚本开始,它显示所有发送的信号:http://www.brendangregg.com/DTrace/kill.d

【讨论】:

  • 您是说即使 LINUX 终端以 SIGKILL 终止也不会将 SIGHUP 发送给它的子进程....虽然感谢脚本,但我会尝试并告诉您。
  • 这确实是我要说的,但是,如果它们是会话领导者被杀死的一组进程的一部分,内核本身可能会向终端子进程发送一个 SIGTERM。这可能就是您在 Linux 下观察到的情况。
  • 在 LINUX 终端下,当终端被杀死时,孩子们确实收到了 SIGHUP 信号,正如我在我的帖子中提到的,也不是 SIGTERM。
  • 我之前的观察有误,您现在可以看一下帖子吗
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-04
  • 2010-12-08
  • 2019-08-01
相关资源
最近更新 更多