当调用者属于后台进程时,tcsetpgrp() 是否成功?

Does tcsetpgrp() succeds when the caller belong to a background process?

根据POSIX specification,如果是后台进程,tcsetpgrp可以导致SIGTTOU被发送到调用进程的组。

但是我不明白在这种情况下是否更改了前景组。

此外,如果尽管信号生成但前景组实际上发生了变化,我想知道如果新的前景组是将要接收 SIGTTOU 的那个,会话和终端会发生什么。

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"。