gpt4 book ai didi

c - 使用 setpgid 将父进程组设置为子进程组失败

转载 作者:太空宇宙 更新时间:2023-11-04 12:15:43 26 4
gpt4 key购买 nike

我正在尝试将进程的 pgrp 更改为子进程的 pgrp,以便我可以在父进程上 setsid。唯一的问题是我不断收到 EPERM 错误代码。根据 htop,这两个进程具有相同的 session 组。

我基于这个 blog post ,因此我可以更改定向到哪个终端输出。

void sig_exit(int signum)
{
_Exit(0);
}

pid_t change_process_group()
{
pid_t child_pid;
if ((child_pid = fork()) < 0)
{
perror("fork failed while attaching to term");
exit(1);
}
if (child_pid == 0)
{
pid_t parent = getppid();
setpgid(0, getpid());

signal(SIGUSR1, sig_exit); // wait till parent tells child to exit

//sleep(5);
//kill(parent, SIGUSR2);
pause();
printf("Shouldn't reach this\n");
}

//sleep(5);
//signal(SIGUSR2, sig_wait);
//pause();
int parent_pid = getpid();
int code = setpgid(parent_pid, child_pid); // need child process group
printf("%s\n", strerror(errno));
setsid();

return child_pid;
}

main()
{
pid_t child = change_process_group();

kill(child, SIGUSR1);
}

注释掉的行是我认为进程可能未按正确顺序执行,但这些似乎无法解决问题。如何正确使用 setpgid 将父进程的 pgrp 更改为子进程的 pgrp?

最佳答案

这是一个竞争条件,如果您取消注释父项中的 sleep(5) 行,它就会起作用。当您调用 setpgid(parent_pid, child_pid) 时,child_pid 进程组 必须存在。仅仅存在具有 PID child_pid 的进程是不够的:setpgid 需要一个现有的进程组,除非该进程将自己放入自己的组中。如果父级中的 setpgid(parent_pid, child_pid) 在子级中的 setpgid(0, getpid()) 之后运行,它将起作用。

sleep 既低效又脆弱,因此 parent 应该等待 child 的通知。信号很脆弱,因为没有很多不同的信号,而且它们可能来自任何地方。在相关进程之间进行通信的一种好方法是管道。由于您在这里只需要一个一次性通知,因此您可以设置一个管道并在父级中从中读取(在父级中关闭写入端)。 parent 将等到 child 写入管道或关闭它。在 child 中,完成准备工作后,只需关闭管道的写入端即可。父级的 read 调用(或 select 如果您需要同时做其他事情)将返回。

概念验证代码:

pid_t change_process_group()
{
pid_t child_pid;
int child_ready_pipe[2];
if (pipe(child_ready_pipe) < 0)
{
perror("pipe");
exit(1);
}
if ((child_pid = fork()) < 0)
{
perror("fork failed while attaching to term");
exit(1);
}
if (child_pid == 0)
{
close(child_ready_pipe[0]);
sleep(1); // mimic slow start of the child
if (setpgid(0, 0))
perror("child setpgid to create group");
close(child_ready_pipe[1]);

signal(SIGUSR1, sig_exit); // wait till parent tells child to exit
pause();
printf("Shouldn't reach this\n");
}

close(child_ready_pipe[1]);
int parent_pid = getpid();
char ignored;
read(child_ready_pipe[0], &ignored, 1);
close(child_ready_pipe[0]);
if (setpgid(parent_pid, child_pid) < 0) // need child process group
perror("parent setpgid");
if (setsid() < 0)
perror("parent setsid");

return child_pid;
}

关于c - 使用 setpgid 将父进程组设置为子进程组失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47521001/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com