结论: 对于支持job control的环境, 后台任务设置为前台任务的后果就是,该后台任务变为前台任务,执行结束后,Terminal自行退出。
测试代码:
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/wait.h>
#include "apue.h"
#include <errno.h>
#include <signal.h>
static void
sig_tou(int signo)
{
printf("SIGTTOU received, pid = %ld\n", (long)getpid());
}
static void
sig_tin(int signo)
{
printf("SIGTTIN received, pid = %ld\n", (long)getpid());
}
static void
sig_int(int signo)
{
printf("SIGTINT received, pid = %ld\n", (long)getpid());
}
void pr_exit(int status);
int main()
{
int pid;
int state;
int fd;
if((fd = open("/dev/tty", O_RDWR))<0)
err_sys("no terminal");
signal(SIGTTOU, SIG_IGN);
signal(SIGTTIN, sig_tin);
signal(SIGINT, sig_int);
if((pid = fork()) == 0)
{
setpgid(0,getpid());
while(tcsetpgrp(fd,getpid())<0){
printf("child:%s\n", strerror(errno));
if(errno == EINTR )
continue;
else
err_sys("child set fail");
}
printf("After tcsetpgrp,the fore process group is %d\n",(int)tcgetpgrp(0));
printf("I am child,process id is %d,process group id is %d\n",getpid(),getpgrp());
exit(6);
}
else
{
setpgid(pid,pid);
while(tcsetpgrp(fd,pid)<0){
if(errno == EINTR )
continue;
else
exit(1);
}
//printf("I am father,process id is %d,process group id is %d\n",getpid(),getpgrp());
//printf("in father perspective,the fore process group is %d\n",(int)tcgetpgrp(0));
while(waitpid(pid, &state, WNOHANG) != pid){}
pr_exit(state);
}
return 0;
}
void
pr_exit(int status)
{
if (WIFEXITED(status))
printf("normal termination, exit status = %d\n", WEXITSTATUS(status));
else if (WIFSIGNALED(status))
printf("abnormal termination, signal number = %d%s\n",
WTERMSIG(status),
#ifdef WCOREDUMP
WCOREDUMP(status) ? " (core file generated)" : "");
#else
"");
#endif
else if (WIFSTOPPED(status))
printf("child stopped, signal number = %d\n", WSTOPSIG(status));
}
MacOSX 13.4.0 本地运行结果:
$ gcc prog.c libapue.a;
$ ./a.out&
[1] 29190
$ After tcsetpgrp,the fore process group is 29191
I am child,process id is 29191,process group id is 29191
normal termination, exit status = 6
logout[Process completed]