Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 当进程的控制外壳被杀死时,优雅地终止进程_C_Linux_Unix_Signals_Solaris - Fatal编程技术网

C 当进程的控制外壳被杀死时,优雅地终止进程

C 当进程的控制外壳被杀死时,优雅地终止进程,c,linux,unix,signals,solaris,C,Linux,Unix,Signals,Solaris,我有一个命令行应用程序。我面临的问题是,有时该应用程序的用户会直接关闭运行应用程序的终端,该终端也会使用以下命令: kill -9 pid_of_parent_console 在上述情况下,我们的应用程序应该通过执行所有必要的清理来优雅地关闭。为此,我编写了一个处理SIGHUP信号的信号处理程序,当进程的控制终端退出时,它将SIGHUP发送给在其下运行的进程,但问题是,如果用户打开一个终端,假设默认情况下是bash,然后他再次在其中键入bash命令,然后运行我们的应用程序,如果假设在打开终端后

我有一个命令行应用程序。我面临的问题是,有时该应用程序的用户会直接关闭运行应用程序的终端,该终端也会使用以下命令:

kill -9 pid_of_parent_console
在上述情况下,我们的应用程序应该通过执行所有必要的清理来优雅地关闭。为此,我编写了一个处理SIGHUP信号的信号处理程序,当进程的控制终端退出时,它将SIGHUP发送给在其下运行的进程,但问题是,如果用户打开一个终端,假设默认情况下是bash,然后他再次在其中键入bash命令,然后运行我们的应用程序,如果假设在打开终端后终止了bash手动执行的应用程序父进程,那么我们的应用程序就不会启动并停止运行不会优雅地退出。为简单起见,我编写了以下代码,重现了该问题:

#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;    
}
#包括
#包括
FILE*fp=NULL;
int标志=1;
无效处理程序(int-signum)
{
flag=0;
}
int main()
{
信号机(信号机、处理器);
//只是为了测试
fp=fopen(“文件”,“w”);
//循环仅在生成HUP时终止
而(旗),;
//如果生成SIGHUP,则代码应到达此处
//并将以下内容写入文件中。
fprintf(fp,“生成的SIGHUP”);
fclose(fp);
返回0;
}
为简单起见,我不使用sigaction来处理信号

我观察到的是,当我打开一个终端并按tty命令并记下与之关联的stdin文件的名称,然后在同一个终端中,如果我输入bash命令并再次使用tty命令记下与之关联的stdin文件,我发现bash shell,在启动终端时默认打开的一个和在bash控制台中键入bash命令手动打开的一个共享相同的stdin文件名

因此,当我杀死作为进程父进程的第二个bash时,与它关联的stdin文件不会关闭,我想这就是为什么我没有收到SIGHUP信号

当进程的控制控制台被终止时,有没有其他方法可以使我的进程过于优雅地终止

使用的终端仿真器:GNOME终端2.31.3
默认shell:bash

无论操作系统如何,
SIGKILL
(即signal
-9
)直接由内核处理,并且在任何用户区处理程序有机会处理任何内容之前,进程被终止。与Solaris内核一样,Linux内核也是如此

因此,目标进程没有办法保护自己不受该信号的影响(除了在发送方或内核中拦截它之外)

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


我建议在Solaris 10机器上使用dtrace来研究这个过程。从显示发送的所有信号的脚本开始:

您使用哪个shell?我在tcsh和Bash中尝试过,因为信号9不可捕获,所以您的终端没有机会执行任何清理,这将是它生成HUP到子进程的地方。您需要重新教育用户不要使用
kill-9
。可能采取极端措施…通过窗口管理器装饰关闭窗口可能会发送SIGTERM而不是SIGHUP,但这可能会因您使用的GUI而异(甚至可能在单个GUI的不同版本中)。无论如何,SIGKILL(也称为kill-9)只能在用尽其他可能性后很少使用。@mSatyam您的进程可以定期检查其PPID(父PID)并在其更改(变为“1”),这意味着父进程死机/崩溃/等等。你是说即使以SIGKILL终止的LINUX终端也不会向其孩子发送SIGHUP…尽管感谢脚本,我会尝试并让你知道。但是,这确实是我要告诉你的,如果终端子进程是会话头被终止的一组进程的一部分,内核本身可能会向它们发送SIGTERM。这可能是你在Linux下观察到的情况。在Linux下,终端被杀死时,孩子们确实收到了SIGHUP信号,正如我在帖子中提到的,而不是SIGTERM。我之前的观察是错误的。你现在可以看帖子了吗