diff --git a/uvloop/handles/process.pxd b/uvloop/handles/process.pxd index c98b48f1..970abcfc 100644 --- a/uvloop/handles/process.pxd +++ b/uvloop/handles/process.pxd @@ -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) diff --git a/uvloop/handles/process.pyx b/uvloop/handles/process.pyx index 89208357..63b982ae 100644 --- a/uvloop/handles/process.pyx +++ b/uvloop/handles/process.pyx @@ -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: @@ -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)) @@ -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) diff --git a/uvloop/includes/uv.pxd b/uvloop/includes/uv.pxd index 595ff899..87651306 100644 --- a/uvloop/includes/uv.pxd +++ b/uvloop/includes/uv.pxd @@ -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 diff --git a/vendor/libuv b/vendor/libuv index 988f2bfc..f0bb7e40 160000 --- a/vendor/libuv +++ b/vendor/libuv @@ -1 +1 @@ -Subproject commit 988f2bfc4defb9a85a536a3e645834c161143ee0 +Subproject commit f0bb7e40f0508bedf6fad33769b3f87bb8aedfa6