On Wed, 13 Sep 2017, Martijn van Duren wrote:
> When reading up on setsid I found ERRORS section confusing. It indicates
> that EPERM may occur if the process group ID of a process other than the
> calling process matches the process ID of the calling process.
>
> To me this appears to be in contradiction with the fork manpage, which
> states: The child process has a unique process ID, which also does not
> match any existing process group ID.
>
> So how can the former occur if the latter states that it's unique?
It may start unique, but PGIDs are shared among processes and a process
change move among process groups. Put those together and you get a
program such as the following, which demonstrates a setsid() call failing
because the process group with the same ID as the target process already
exists.
So nope, the manpage is correct as is.
Philip Guenther
--------
#include <sys/wait.h>
#include <err.h>
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
int
main(void)
{
pid_t c1, c2, g;
ssize_t len;
int fds[2];
int ch, status;
printf("p:\t%d\t%d\n", getpid(), getpgrp());
if (pipe(fds))
err(1, "pipe");
if ((c1 = fork()) == -1)
err(1, "fork %d", 1);
if (c1 == 0) {
close(fds[0]);
printf("c1:\t%d\t%d\n", getpid(), getpgrp());
if (setpgrp(0, 0))
err(1, "setpgrp");
printf("c1:\t%d\t%d\n", getpid(), getpgrp());
if (write(fds[1], "", 1) != 1)
err(1, "write");
close(fds[1]);
sleep(60);
_exit(0);
}
close(fds[1]);
if ((len = read(fds[0], &ch, 1)) == -1)
err(1, "read");
if (len != 1) {
waitpid(c1, &status, 0);
errx(1, "c1: %#x", status);
}
close(fds[0]);
if (pipe(fds))
err(1, "pipe");
if ((c2 = fork()) == -1)
err(1, "fork %d", 2);
if (c2 == 0) {
close(fds[0]);
printf("c2:\t%d\t%d\n", getpid(), getpgrp());
if (setpgrp(0, 0))
err(1, "setpgrp");
printf("c2:\t%d\t%d\n", getpid(), getpgrp());
if ((g = fork()) == -1)
err(1, "fork %d", 3);
if (g == 0) {
printf("g:\t%d\t%d\n", getpid(), getpgrp());
close(fds[0]);
close(fds[1]);
sleep(60);
_exit(0);
}
if ((len = write(fds[1], &g, sizeof g)) == -1)
err(1, "write pid");
if (len != (int)sizeof g)
errx(1, "write %zd != %zu", len, sizeof g);
close(fds[1]);
if (setpgid(0, c1))
err(1, "setpgrp");
printf("c2:\t%d\t%d\n", getpid(), getpgrp());
if (setsid())
err(1, "setsid");
_exit(0);
}
waitpid(c2, &status, 0);
if (kill(c1, SIGINT))
err(1, "kill");
return 0;
}