def spawnv_passfds(path, args, passfds): import _posixsubprocess passfds = sorted(passfds) errpipe_read, errpipe_write = os.pipe() try: return _posixsubprocess.fork_exec( args, [os.fsencode(path)], True, passfds, None, None, -1, -1, -1, -1, -1, -1, errpipe_read, errpipe_write, False, False, None, ) finally: os.close(errpipe_read) os.close(errpipe_write)
def spawnv_passfds(path, args, passfds): passfds = sorted(passfds) errpipe_read, errpipe_write = os.pipe() try: return _posixsubprocess.fork_exec( args, [fsencode(path)], True, tuple(passfds), None, None, -1, -1, -1, -1, -1, -1, errpipe_read, errpipe_write, False, False, None, ) finally: os.close(errpipe_read) os.close(errpipe_write)
def spawnv_passfds(path, args, passfds): import _posixsubprocess passfds = tuple(sorted(map(int, passfds))) errpipe_read, errpipe_write = os.pipe() # iOS: just return fork_exec, don't close the threads. if (sys.platform == 'darwin' and os.uname().machine.startswith('iP')): return _posixsubprocess.fork_exec(args, [os.fsencode(path)], True, passfds, None, None, -1, -1, -1, -1, -1, -1, errpipe_read, errpipe_write, False, False, None, None, None, -1, None) try: return _posixsubprocess.fork_exec(args, [os.fsencode(path)], True, passfds, None, None, -1, -1, -1, -1, -1, -1, errpipe_read, errpipe_write, False, False, None, None, None, -1, None) finally: os.close(errpipe_read) os.close(errpipe_write)
def spawnv_passfds(path, args, passfds): import _posixsubprocess passfds = tuple(sorted(map(int, passfds))) errpipe_read, errpipe_write = os.pipe() try: return _posixsubprocess.fork_exec(args, [os.fsencode(path)], True, passfds, None, None, -1, -1, -1, -1, -1, -1, errpipe_read, errpipe_write, False, False, None) finally: os.close(errpipe_read) os.close(errpipe_write)
def spawnv_passfds(path, args, passfds): passfds = sorted(passfds) errpipe_read, errpipe_write = os.pipe() try: args = [ args, [fsencode(path)], True, tuple(passfds), None, None, -1, -1, -1, -1, -1, -1, errpipe_read, errpipe_write, False, False ] if sys.version_info >= (3, 9): args.extend( (None, None, None, -1)) # group, extra_groups, user, umask args.append(None) # preexec_fn return _posixsubprocess.fork_exec(*args) finally: os.close(errpipe_read) os.close(errpipe_write)
def spawnv_passfds(path, args, passfds): passfds = sorted(passfds) errpipe_read, errpipe_write = os.pipe() try: if sys.version_info >= (3, 3): import _posixsubprocess return _posixsubprocess.fork_exec( args, [os.fsencode(path)], True, passfds, None, None, -1, -1, -1, -1, -1, -1, errpipe_read, errpipe_write, False, False, None) else: from .reduction import _mk_inheritable _pass = [] for fd in passfds: _pass += [_mk_inheritable(fd)] from .fork_exec import fork_exec fork_exec(args, _pass) finally: os.close(errpipe_read) os.close(errpipe_write)
def spawnv_passfds(path, args, passfds): if sys.platform == 'vxworks': import _vxwapi else: import _posixsubprocess passfds = tuple(sorted(map(int, passfds))) errpipe_read, errpipe_write = os.pipe() try: if sys.platform == 'vxworks': return _vxwapi.rtp_spawn(args, [os.fsencode(path)], True, passfds, None, None, -1, -1, -1, -1, -1, -1, errpipe_read, errpipe_write, False, False, None) else: return _posixsubprocess.fork_exec(args, [os.fsencode(path)], True, passfds, None, None, -1, -1, -1, -1, -1, -1, errpipe_read, errpipe_write, False, False, None, None, None, -1, None) finally: os.close(errpipe_read) os.close(errpipe_write)
def spawnv_passfds(path, args, passfds): import _posixsubprocess, fcntl passfds = sorted(passfds) tmp = [] # temporarily unset CLOEXEC on passed fds for fd in passfds: flag = fcntl.fcntl(fd, fcntl.F_GETFD) if flag & fcntl.FD_CLOEXEC: fcntl.fcntl(fd, fcntl.F_SETFD, flag & ~fcntl.FD_CLOEXEC) tmp.append((fd, flag)) errpipe_read, errpipe_write = _posixsubprocess.cloexec_pipe() try: return _posixsubprocess.fork_exec( args, [os.fsencode(path)], True, passfds, None, None, -1, -1, -1, -1, -1, -1, errpipe_read, errpipe_write, False, False, None) finally: os.close(errpipe_read) os.close(errpipe_write) # reset CLOEXEC where necessary for fd, flag in tmp: fcntl.fcntl(fd, fcntl.F_SETFD, flag)
def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, start_new_session): if isinstance(args, (str, bytes)): args = [args] else: args = list(args) if shell: args = ['/bin/sh', '-c'] + args if executable: args[0] = executable if executable is None: executable = args[0] orig_executable = executable (errpipe_read, errpipe_write) = _create_pipe() try: try: if env is not None: env_list = [os.fsencode(k) + b'=' + os.fsencode(v) for (k, v) in env.items()] else: env_list = None executable = os.fsencode(executable) if os.path.dirname(executable): executable_list = (executable,) else: executable_list = tuple(os.path.join(os.fsencode(dir), executable) for dir in os.get_exec_path(env)) fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self.pid = _posixsubprocess.fork_exec(args, executable_list, close_fds, sorted(fds_to_keep), cwd, env_list, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, errpipe_read, errpipe_write, restore_signals, start_new_session, preexec_fn) self._child_created = True finally: os.close(errpipe_write) devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) self._closed_child_pipe_fds = True errpipe_data = bytearray() while True: part = _eintr_retry_call(os.read, errpipe_read, 50000) errpipe_data += part if not part or len(errpipe_data) > 50000: break finally: os.close(errpipe_read) if errpipe_data: try: _eintr_retry_call(os.waitpid, self.pid, 0) except OSError as e: while e.errno != errno.ECHILD: raise try: (exception_name, hex_errno, err_msg) = errpipe_data.split(b':', 2) except ValueError: exception_name = b'RuntimeError' hex_errno = b'0' err_msg = b'Bad exception data from child: ' + repr(errpipe_data) child_exception_type = getattr(builtins, exception_name.decode('ascii'), RuntimeError) err_msg = err_msg.decode(errors='surrogatepass') if issubclass(child_exception_type, OSError) and hex_errno: errno_num = int(hex_errno, 16) child_exec_never_called = err_msg == 'noexec' if child_exec_never_called: err_msg = '' if errno_num != 0: err_msg = os.strerror(errno_num) if errno_num == errno.ENOENT: if child_exec_never_called: err_msg += ': ' + repr(cwd) else: err_msg += ': ' + repr(orig_executable) raise child_exception_type(errno_num, err_msg) raise child_exception_type(err_msg)
def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, start_new_session): if isinstance(args, types.StringTypes): args = [args] else: args = list(args) if shell: args = ['/bin/sh', '-c'] + args if executable: args[0] = executable if executable is None: executable = args[0] errpipe_read, errpipe_write = _create_pipe() try: try: if _posixsubprocess: fs_encoding = sys.getfilesystemencoding() def fs_encode(s): if isinstance(s, str): return s else: return s.encode(fs_encoding, 'strict') if env is not None: env_list = [ fs_encode(k) + '=' + fs_encode(v) for k, v in env.items() ] else: env_list = None if os.path.dirname(executable): executable_list = (fs_encode(executable),) else: path_list = _get_exec_path(env) executable_list = (os.path.join(dir, executable) for dir in path_list) executable_list = tuple((fs_encode(exe) for exe in executable_list)) fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self.pid = _posixsubprocess.fork_exec(args, executable_list, close_fds, sorted(fds_to_keep), cwd, env_list, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, errpipe_read, errpipe_write, restore_signals, start_new_session, preexec_fn) self._child_created = True else: gc_was_enabled = gc.isenabled() gc.disable() try: self.pid = os.fork() except: if gc_was_enabled: gc.enable() raise self._child_created = True if self.pid == 0: try: if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) if errwrite == 0 or errwrite == 1: errwrite = os.dup(errwrite) def _dup2(a, b): if a == b: _set_cloexec(a, False) elif a != -1: os.dup2(a, b) _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) closed = set() for fd in [p2cread, c2pwrite, errwrite]: if fd > 2 and fd not in closed: os.close(fd) closed.add(fd) if close_fds: if pass_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_all_but_a_sorted_few_fds(sorted(fds_to_keep)) else: self._close_fds(but=errpipe_write) if cwd is not None: os.chdir(cwd) if restore_signals: signals = ('SIGPIPE', 'SIGXFZ', 'SIGXFSZ') for sig in signals: if hasattr(signal, sig): signal.signal(getattr(signal, sig), signal.SIG_DFL) if start_new_session and hasattr(os, 'setsid'): os.setsid() if preexec_fn: preexec_fn() if env is None: os.execvp(executable, args) else: os.execvpe(executable, args, env) except: try: exc_type, exc_value = sys.exc_info()[:2] if isinstance(exc_value, OSError): errno_num = exc_value.errno else: errno_num = 0 message = '%s:%x:%s' % (exc_type.__name__, errno_num, exc_value) os.write(errpipe_write, message) except Exception: pass os._exit(255) if gc_was_enabled: gc.enable() finally: os.close(errpipe_write) if p2cread != -1 and p2cwrite != -1: os.close(p2cread) if c2pwrite != -1 and c2pread != -1: os.close(c2pwrite) if errwrite != -1 and errread != -1: os.close(errwrite) data = '' while True: part = _eintr_retry_call(os.read, errpipe_read, 50000) data += part if not part or len(data) > 50000: break finally: os.close(errpipe_read) if data != '': try: _eintr_retry_call(os.waitpid, self.pid, 0) except OSError as e: if e.errno != errno.ECHILD: raise try: exception_name, hex_errno, err_msg = data.split(':', 2) except ValueError: print 'Bad exception data:', repr(data) exception_name = 'RuntimeError' hex_errno = '0' err_msg = 'Unknown' child_exception_type = getattr(exceptions, exception_name, RuntimeError) for fd in (p2cwrite, c2pread, errread): if fd != -1: os.close(fd) if issubclass(child_exception_type, OSError) and hex_errno: errno_num = int(hex_errno, 16) if errno_num != 0: err_msg = os.strerror(errno_num) if errno_num == errno.ENOENT: err_msg += ': ' + repr(args[0]) raise child_exception_type(errno_num, err_msg) try: exception = child_exception_type(err_msg) except Exception: exception = RuntimeError('Could not re-raise %r exception from the child with error message %r' % (child_exception_type, err_msg)) raise exception