According to the man setpgid(2)
page,
EACCES An attempt was made to change the process group ID of one of the children of the calling process and the child had already performed an execve(2) (setpgid(), setpgrp()).
ESRCH For getpgid(): pid does not match any process. For setpgid(): pid is not the calling process and not a child of the calling process.
The errno should be EACCES
according to the description. But why do I get ESRCH
instead?
#include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <errno.h> void print_errno() { if (errno == EACCES) printf("errno: EACCESn"); else if (errno == EPERM) printf("errno: EPERMn"); else if (errno == ESRCH) printf("errno: ESRCHn"); } #define CHECK(syscall, msg) do { if ((syscall) == -1) { print_errno(); perror(msg); _exit(1); } } while(0) int main () { int ls_pid; char *ls_argv[] = { "ls", NULL }; CHECK(ls_pid = fork(), "fork error"); if (!ls_pid) { CHECK(execvp(ls_argv[0], ls_argv), "execvp error"); } else { sleep(2); CHECK(setpgid(ls_pid, ls_pid), "setpgid error"); CHECK(wait(NULL), "wait error"); printf("Finishn"); } }
Advertisement
Answer
The specification of setpgid
does not say what error is to be returned by setpgid
when the pid argument refers to a zombie child of the calling process, whether or not it called execve
. Thus, this is not technically a bug.
ESRCH
makes sense if you consider that zombies aren’t really processes anymore; they’re just the data that needs to stick around until someone gets around to calling wait
. For instance, it would make a lot of sense for kill
to fail with ESRCH
when applied to a zombie.
I’d like to close with some observations on how this is actually implemented, but, alas, I looked at the source code for setpgid
in Linux and could not figure out what it would return for this case, because Linux’s namespace support has turned many process-related syscalls into horrible mazes of spaghetti. So then I tried to look at FreeBSD instead and I couldn’t even find the relevant part of the source code, because the file-level organization of the FreeBSD kernel is incomprehensible. So you’re going to have to do without, sorry.