Skip to content

Commit

Permalink
Fallback to fork() on macOS if preexec_fn is set
Browse files Browse the repository at this point in the history
  • Loading branch information
fantix committed Oct 11, 2023
1 parent 2684057 commit d7b9df7
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 3 deletions.
2 changes: 1 addition & 1 deletion uvloop/handles/process.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ cdef class UVProcess(UVHandle):
cdef _init_env(self, dict env)
cdef _init_files(self, _stdin, _stdout, _stderr)
cdef _init_options(self, list args, dict env, cwd, start_new_session,
_stdin, _stdout, _stderr)
_stdin, _stdout, _stderr, bint force_fork)

cdef _close_after_spawn(self, int fd)

Expand Down
27 changes: 25 additions & 2 deletions uvloop/handles/process.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,17 @@ cdef class UVProcess(UVHandle):
# callbacks have a chance to avoid casting *something* into UVHandle.
self._handle.data = NULL

force_fork = False
if system.PLATFORM_IS_APPLE and not (
preexec_fn is None
and not pass_fds
):
# see _execute_child() in CPython/subprocess.py
force_fork = True

try:
self._init_options(args, env, cwd, start_new_session,
_stdin, _stdout, _stderr)
_stdin, _stdout, _stderr, force_fork)

restore_inheritable = set()
if pass_fds:
Expand Down Expand Up @@ -232,7 +240,7 @@ cdef class UVProcess(UVHandle):
return ret

cdef _init_options(self, list args, dict env, cwd, start_new_session,
_stdin, _stdout, _stderr):
_stdin, _stdout, _stderr, bint force_fork):

memset(&self.options, 0, sizeof(uv.uv_process_options_t))

Expand All @@ -246,6 +254,21 @@ cdef class UVProcess(UVHandle):
if start_new_session:
self.options.flags |= uv.UV_PROCESS_DETACHED

if force_fork:
# This is a hack to work around the change in libuv 1.44:
# > macos: use posix_spawn instead of fork
# where Python subprocess options like preexec_fn are
# crippled. CPython only uses posix_spawn under a pretty
# strict list of conditions (see subprocess.py), and falls
# back to using fork() otherwise. We'd like to simulate such
# behavior with libuv, but unfortunately libuv doesn't
# provide explicit API to choose such implementation detail.
# Based on current (libuv 1.46) behavior, setting
# UV_PROCESS_SETUID or UV_PROCESS_SETGID would reliably make
# libuv fallback to use fork, so let's just use it for now.
self.options.flags |= uv.UV_PROCESS_SETUID
self.options.uid = uv.getuid()

if cwd is not None:
cwd = os_fspath(cwd)

Expand Down
1 change: 1 addition & 0 deletions uvloop/includes/uv.pxd
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from libc.stdint cimport uint16_t, uint32_t, uint64_t, int64_t
from posix.types cimport gid_t, uid_t
from posix.unistd cimport getuid

from . cimport system

Expand Down

0 comments on commit d7b9df7

Please sign in to comment.