On Tue, Jun 27, 2023 at 09:27:17PM +0000, Laurent Bercot wrote: > Testing the behaviour may be challenging, however, because I suspect > the CentOS 7 implementation of posix_spawn() is just racy, and they > simply documented that they don't care.
Actually I copied the fragment of posix_spawn(3) from a Devuan Chimaera machine, so the problem may be not specific to CentOS 7. I did not test CentOS 6 or other distro (version)s, for example; but on Rocky Linux 8, which I unfortunately also need to support at work, the behaviour is as expected. Attached is a simple test. >From the posix_spawn(3), which had the similar statement across the three different versions above, there is also a statement two paragraphs later: "The posix_spawn() and posix_spawnp() functions fail only in the case where the underlying fork(2), vfork(2) or clone(2) call fails". So if the manpage is followed to the word, the CentOS 7 behaviour is expected; if posix_spawn(3p) is followed instead, any exec() error must also be caught and result in returning 0, which we really expect. If we assume posix_spawn(3) and posix_spawn(3p) were the only possible behaviours (which is frankly not that reliable, judging from how neither manpage noted the violation of conformance), then the two behaviours could be distinguished with the attached test. -- My current OpenPGP key: RSA4096/0x227E8CAAB7AA186C (expires: 2024.09.30) 7077 7781 B859 5166 AE07 0286 227E 8CAA B7AA 186C
/* ISC license. */ #include <errno.h> #include <signal.h> #include <spawn.h> #include <stdio.h> #include <stdlib.h> pid_t child_spawn0 (char const *prog, char const *const *argv, char const *const *envp) { pid_t pid ; posix_spawnattr_t attr ; int e ; e = posix_spawnattr_init(&attr) ; if (e) goto err ; e = posix_spawnp(&pid, prog, 0, &attr, (char *const *)argv, (char *const *)envp) ; posix_spawnattr_destroy(&attr) ; if (e) goto err ; return pid ; err: errno = e ; return 0 ; } int main (int argc, char const *const *argv, char const *const *envp) { if (argc < 2) return 1 ; printf ("%d\n", child_spawn0(argv[1], &argv[1], envp)) ; return 0 ; }