根据POSIX specification,tcsetpgrp
可以导致SIGTTOU
被发送到调用进程的组(如果它是后台进程)。
但是,如果在这种情况下前景组被更改,我无法理解。
此外,如果尽管信号生成实际上改变了前景组,我想知道如果新的前景组是将要接收SIGTTOU
的那个,会话和终端会发生什么。
答案 0 :(得分:1)
<强> TL:DR:强>
没有前景组不会改变。这是有道理的,因为当进程改变终端上的设置 - 输出操作时,应该发送信号。如果更改成功,信号也不会传递给进程(现在是前台组),因为如果没有人发送SIGCONT,它就会卡住。
更长的回答:
一个简单的例子:
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <signal.h>
void sig(int signo) {
const char* msg = strsignal(signo); // XXX: Not async-signal-safe.
write(STDOUT_FILENO, msg, strlen(msg));
write(STDOUT_FILENO, "\n", 1);
}
int main() {
char cntl_tty[L_ctermid];
ctermid(cntl_tty);
signal(SIGTTOU, sig);
signal(SIGCONT, sig);
int fd = open(cntl_tty, O_RDONLY);
if (fd == -1) {
perror("open");
exit(1);
}
if (tcsetpgrp(fd, getpgrp()) == -1) {
perror("tcsetpgrp");
} else {
puts("foregrounded");
}
return 0;
}
当此代码作为后台进程启动并处理SIGTTOU
时,此循环将永久打印以接收信号。永远不会调用perror
,这意味着内核重新启动系统调用。发送SIGCONT
并不重要。前景永远不会成功。但是,当通过shell前景化代码时,“foregrounded”将按预期打印。
当SIGTTOU
的信号处理方式更改为SIG_IGN
时,会立即打印“foregrounded”。