在GNU libc关于orphaned process groups的手册中,它提到了:
“process groups that continue running even after the session leader
has terminated are marked as orphaned process groups.
When a process group becomes an orphan, its processes are sent a SIGHUP
signal. Ordinarily, this causes the processes to terminate. However,
if a program ignores this signal or establishes a handler for it
(see Signal Handling), it can continue running as in the orphan process
group even after its controlling process terminates; but it still
cannot access the terminal any more. ”
我编写了一个测试程序,但是当进程组成为孤儿时,它的进程没有收到SIGHUP信号。我想知道为什么?
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
static void
sig_hup(int signo) //**never get called ???**
{
printf("SIGHUP received, pid = %ld\n", (long)getpid());
}
static void
pr_ids(char *name)
{
printf("%s: pid = %ld, ppid = %ld, pgrp = %ld, tpgrp = %ld\n",
name, (long)getpid(), (long)getppid(), (long)getpgrp(),
(long)tcgetpgrp(STDIN_FILENO));
fflush(stdout);
}
int
main(void)
{
char c;
pid_t pid;
pr_ids("parent");
pid = fork();
if (pid > 0) { // parent
sleep(5);
exit(0); // parent exit;
} else {
pr_ids("child");
setsid(); //create new session, and "child" becomes the session leader
pid = fork();
if(pid>0) {
sleep(20);
exit(0); // "child" exit
// so the process group become an orphan process group
}
else{
pr_ids("grandson");
signal(SIGHUP, sig_hup); // establish signal handler
sleep(60); // now becoming orphan process group
printf("end\n");
}
}
exit(0);
}
答案 0 :(得分:2)
如果孤立的进程组在孤立时被拦截,则会获得SIGHUP,然后是SIGCONT。
睡眠不够,你需要:
kill(getpid(), SIGSTOP);
除此之外,如果孤立是由setsid()
或setprgrp()
引起的,POSIX不要求发送SIGHUP和SIGCONT,因为它不是由一个无意识地没有意识到的退出进程引起的工作控制(见http://pubs.opengroup.org/onlinepubs/9699919799/functions/_exit.html)。
但是,使用kill(getpid(), SIGSTOP)
代替孩子中的sleep(60)
,即使您没有拨打setsid()
,您的程序也会获得已停止的孤儿。
#define _GNU_SOURCE
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <signal.h>
static void
sig_hup(int signo) //**never get called ???**
{
printf("SIGHUP received, pid = %ld\n", (long)getpid());
}
static void
pr_ids(char *name)
{
printf("%s: pid = %ld, ppid = %ld, pgrp = %ld, tpgrp = %ld\n",
name, (long)getpid(), (long)getppid(), (long)getpgrp(),
(long)tcgetpgrp(STDIN_FILENO));
fflush(stdout);
}
int
main(void)
{
pid_t pid;
pr_ids("parent");
pid = fork();
if (pid > 0) { // parent
sleep(5);
_exit(0); // parent exit;
} else {
pr_ids("child");
/*setsid(); //create new session, and "child" becomes the session leader*/
pid = fork();
if(pid>0) {
sleep(2);
exit(0); // "child" exit
// so the process group become an orphan process group
}
else{
pr_ids("grandson");
signal(SIGHUP, sig_hup); // establish signal handler
kill(getpid(), SIGSTOP);
printf("end\n");
}
}
exit(0);
}
在父母去世(5s)后,应该在孩子身上得到一个SIGHUP。
答案 1 :(得分:0)
该文档部分专门讨论了一个进程的控制终端的丢失 - 通常是通过调制解调器挂断或虚拟等效(结束ssh会话等)。 (我认为文件中的措词可以在这里改进)。当您在此处使用setsid()
时,您会在setsid()
返回时放弃对控制终端的访问权限,因此没有控制终端会从此处丢失。
你可以open()
tty设备(例如pty slave)获得一个控制终端(注意你可能还需要做一些额外的操作 - FreeBSD需要一个TIOCSCTTY
ioctl),然后再次失去它,然后你应该得到SIGHUP
信号。