bpo-35823: Allow setsid() after vfork() on Linux. (GH-22945)

It should just be a syscall updating a couple of fields in the kernel side
process info.  Confirming, in glibc is appears to be a shim for the setsid
syscall (based on not finding any code implementing anything special for it)
and in uclibc (*much* easier to read) it is clearly just a setsid syscall shim.

A breadcrumb _suggesting_ that it is not allowed on Darwin/macOS comes from
a commit in emacs: https://lists.gnu.org/archive/html/bug-gnu-emacs/2017-04/msg00297.html
but I don't have a way to verify if that is true or not.
As we are not supporting vfork on macOS today I just left a note in a comment.
This commit is contained in:
Gregory P. Smith 2020-10-24 12:07:35 -07:00 committed by GitHub
parent 8cd1dbae32
commit be3c3a0e46
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 3 additions and 2 deletions

View File

@ -38,6 +38,8 @@
#if defined(__linux__) && defined(HAVE_VFORK) && defined(HAVE_SIGNAL_H) && \ #if defined(__linux__) && defined(HAVE_VFORK) && defined(HAVE_SIGNAL_H) && \
defined(HAVE_PTHREAD_SIGMASK) && !defined(HAVE_BROKEN_PTHREAD_SIGMASK) defined(HAVE_PTHREAD_SIGMASK) && !defined(HAVE_BROKEN_PTHREAD_SIGMASK)
/* If this is ever expanded to non-Linux platforms, verify what calls are
* allowed after vfork(). Ex: setsid() may be disallowed on macOS? */
# include <signal.h> # include <signal.h>
# define VFORK_USABLE 1 # define VFORK_USABLE 1
#endif #endif
@ -712,7 +714,6 @@ do_fork_exec(char *const exec_array[],
#ifdef VFORK_USABLE #ifdef VFORK_USABLE
if (child_sigmask) { if (child_sigmask) {
/* These are checked by our caller; verify them in debug builds. */ /* These are checked by our caller; verify them in debug builds. */
assert(!call_setsid);
assert(!call_setuid); assert(!call_setuid);
assert(!call_setgid); assert(!call_setgid);
assert(!call_setgroups); assert(!call_setgroups);
@ -997,7 +998,7 @@ subprocess_fork_exec(PyObject* self, PyObject *args)
/* Use vfork() only if it's safe. See the comment above child_exec(). */ /* Use vfork() only if it's safe. See the comment above child_exec(). */
sigset_t old_sigs; sigset_t old_sigs;
if (preexec_fn == Py_None && if (preexec_fn == Py_None &&
!call_setuid && !call_setgid && !call_setgroups && !call_setsid) { !call_setuid && !call_setgid && !call_setgroups) {
/* Block all signals to ensure that no signal handlers are run in the /* Block all signals to ensure that no signal handlers are run in the
* child process while it shares memory with us. Note that signals * child process while it shares memory with us. Note that signals
* used internally by C libraries won't be blocked by * used internally by C libraries won't be blocked by