https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=251227
Bug ID: 251227 Summary: setpgid sometimes returns ESRCH instead of EACCES Product: Base System Version: 12.2-RELEASE Hardware: Any OS: Any Status: New Severity: Affects Many People Priority: --- Component: kern Assignee: b...@freebsd.org Reporter: mqu...@neosmart.net setpgid(2) says > [ESRCH] The requested process does not exist. > [ESRCH] The target process is not the calling process or a > child of the calling process. > [EACCES] The requested process is a child of the calling > process, but it has performed an exec(3) operation. However, as demonstrated by the following test, FreeBSD is incorrectly returning ESRCH when setpgid(2) is called on a child that has called both fork(2) and execv(3) by the time the parent calls setpgid(2). ``` #include <assert.h> #include <errno.h> #include <stdio.h> #include <unistd.h> int main() { pid_t pid = vfork(); if (pid == 0) { // Child process char * const argv[] = { "env", "true", NULL }; execv("/usr/bin/env", argv); assert(0 && "child returned after execv!"); } // Parent process sleep(1); int result = setpgid(pid, pid); assert(result != 0); printf("error code: %d\n", errno); assert(errno == EACCES && "incorrect error code returned!"); return 0; } ``` The test above fails on FreeBSD 11.2 and FreeBSD 12.2; it passes on Linux. The underlying issue appears to be some sort of race condition: the implementation of sys_setpgid in sys/kern/kern_prot.c correctly checks for the P_EXEC flag and sets errno to EACCES if present. You'll notice the use of vfork(2) in the test above, which, though not guaranteed, in practice blocks execution of the parent process until exec(3) has been called in the child. If the sleep(1) call is omitted from the test, the test passes (EACCES is returned because execv(3) has been called by the child process). With or without the call to sleep(1), the unreaped child process remains present until the parent terminates (i.e. the referenced target pid does exist). Fundamentally, the behavior of the parent (and in particular, the return code from its call to setpgid) should be the same both with and without the call to sleep(1), given the semantics of vfork(3). (The behavior does not change if /usr/bin/true is spawned directly instead of via /usr/bin/env, i.e. this is not an issue with child vs grandchild.) -- You are receiving this mail because: You are the assignee for the bug. _______________________________________________ freebsd-bugs@freebsd.org mailing list https://lists.freebsd.org/mailman/listinfo/freebsd-bugs To unsubscribe, send any mail to "freebsd-bugs-unsubscr...@freebsd.org"