def _execute_child(self, args, executable, preexec_fn, close_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, to_close, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite): """Execute program using posix spawn""" if isinstance(args, (str, bytes)): args = [args] if shell: args = ["/bin/sh", "-c"] + args if executable == None: executable = args[0] sfa = SpawnFileAction() # Child file actions # Close parent's pipe ends closed_fds = [] if p2cwrite: sfa.add_close(p2cwrite) closed_fds.append(p2cwrite) if c2pread: sfa.add_close(c2pread) closed_fds.append(c2pread) if errread: sfa.add_close(errread) closed_fds.append(errread) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) if errwrite == 0 or errwrite == 1: errwrite = os.dup(errwrite) # Dup fds for child if p2cread: sfa.add_dup2(p2cread, 0) if c2pwrite: sfa.add_dup2(c2pwrite, 1) if errwrite: sfa.add_dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once. if p2cread: sfa.add_close(p2cread) closed_fds.append(p2cread) if c2pwrite and c2pwrite not in (p2cread, ): sfa.add_close(c2pwrite) closed_fds.append(c2pwrite) if errwrite and errwrite not in (p2cread, c2pwrite): sfa.add_close(errwrite) closed_fds.append(errwrite) if cwd != None: os.chdir(cwd) if preexec_fn: preexec_fn() # Close all other fds, if asked for - after # preexec_fn(), which may open FDs. if close_fds: # # This is a bit tricky. Due to a sad # behaviour with posix_spawn in nevada # builds before the fix for 6807216 (in # nevada 110), (and perhaps on other OS's?) # you can't have two close actions close the # same FD, or an error results. So we track # everything we have closed, then manually # fstat and close up to the max we have # closed) . Then we close everything above # that efficiently with add_close_childfds(). # for i in range(3, max(closed_fds) + 1): # scheduled closed already? skip if i in closed_fds: continue try: os.fstat(i) sfa.add_close(i) closed_fds.append(i) except OSError: pass closefrom = max([3, max(closed_fds) + 1]) sfa.add_close_childfds(closefrom) if env is None: # If caller didn't pass us an environment in # env, borrow the env that the current process # is using. env = os.environ.copy() if type(env) == dict: # The bundled subprocess module takes a dict in # the "env" argument. Allow that here by doing # the explicit conversion to a list. env = [ "{0}={1}".format(k, v) for k, v in six.iteritems(env) ] self.pid = posix_spawnp(executable, args, sfa, env) self._child_created = True if to_close: def _close_in_parent(fd): os.close(fd) to_close.remove(fd) else: def _close_in_parent(fd): os.close(fd) # Parent if p2cread and p2cwrite: _close_in_parent(p2cread) if c2pwrite and c2pread: _close_in_parent(c2pwrite) if errwrite and errread: _close_in_parent(errwrite)
def _execute_child(self, args, executable, preexec_fn, close_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite): """Execute program using posix spawn""" if isinstance(args, types.StringTypes): args = [args] if shell: args = ["/bin/sh", "-c"] + args if executable == None: executable = args[0] sfa = SpawnFileAction() # Child file actions # Close parent's pipe ends closed_fds = [] if p2cwrite: sfa.add_close(p2cwrite) closed_fds.append(p2cwrite) if c2pread: sfa.add_close(c2pread) closed_fds.append(c2pread) if errread: sfa.add_close(errread) closed_fds.append(errread) # Dup fds for child if p2cread: sfa.add_dup2(p2cread, 0) if c2pwrite: sfa.add_dup2(c2pwrite, 1) if errwrite: sfa.add_dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once. if p2cread: sfa.add_close(p2cread) closed_fds.append(p2cread) if c2pwrite and c2pwrite not in (p2cread,): sfa.add_close(c2pwrite) closed_fds.append(c2pwrite) if errwrite and errwrite not in (p2cread, c2pwrite): sfa.add_close(errwrite) closed_fds.append(errwrite) # Close all other fds, if asked for. if close_fds: # # This is a bit tricky. Due to a sad # behaviour with posix_spawn in nevada # builds before the fix for 6807216 (in # nevada 110), (and perhaps on other OS's?) # you can't have two close actions close the # same FD, or an error results. So we track # everything we have closed, then manually # fstat and close up to the max we have # closed) . Then we close everything above # that efficiently with add_close_childfds(). # for i in range(3, max(closed_fds) + 1): # scheduled closed already? skip if i in closed_fds: continue try: os.fstat(i) sfa.add_close(i) closed_fds.append(i) except OSError: pass closefrom = max([3, max(closed_fds) + 1]) sfa.add_close_childfds(closefrom) if cwd != None: os.chdir(cwd) if preexec_fn: apply(preexec_fn) if not env: # If caller didn't pass us an environment in # env, borrow the env that the current process # is using. env = [ "%s=%s" % (k, v) for k, v in\ os.environ.items() ] self.pid = posix_spawnp(executable, args, sfa, env) # Parent if p2cread and p2cwrite: os.close(p2cread) if c2pwrite and c2pread: os.close(c2pwrite) if errwrite and errread: os.close(errwrite)
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] if shell: args = ["/bin/sh", "-c"] + args if executable is None: executable = args[0] sfa = SpawnFileAction() # Child file actions # Close parent's pipe ends closed_fds = [] if p2cwrite != -1: sfa.add_close(p2cwrite) closed_fds.append(p2cwrite) if c2pread != -1: sfa.add_close(c2pread) closed_fds.append(c2pread) if errread != -1: sfa.add_close(errread) closed_fds.append(errread) # Dup fds for child if p2cread != -1: sfa.add_dup2(p2cread, 0) if c2pwrite != -1: sfa.add_dup2(c2pwrite, 1) if errwrite != -1: sfa.add_dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. for fd in [p2cread, c2pwrite, errwrite]: if fd > 2 and fd not in closed_fds: sfa.add_close(fd) closed_fds.append(fd) if cwd is not None: os.chdir(cwd) if preexec_fn: preexec_fn() # Close all other fds, if asked for - after # preexec_fn(), which may open FDs. if close_fds: # # This is a bit tricky. Due to a sad # behaviour with posix_spawn in nevada # builds before the fix for 6807216 (in # nevada 110), (and perhaps on other OS's?) # you can't have two close actions close the # same FD, or an error results. So we track # everything we have closed, then manually # fstat and close up to the max we have # closed) . Then we close everything above # that efficiently with add_close_childfds(). # # max() can't call on empty list, use a # trick "close_fds or [0]" to return 0 # when closed_fds is empty. for i in range(3, max(closed_fds or [0]) + 1): # scheduled closed already? skip if i in closed_fds: continue try: os.fstat(i) sfa.add_close(i) closed_fds.append(i) except OSError: pass closefrom = max([3, max(closed_fds or [0]) + 1]) sfa.add_close_childfds(closefrom) if env is None: # If caller didn't pass us an environment in # env, borrow the env that the current process # is using. env = os.environ.copy() if type(env) == dict: # The bundled subprocess module takes a dict in # the "env" argument. Allow that here by doing # the explicit conversion to a list. env = [ "{0}={1}".format(k, v) for k, v in six.iteritems(env) ] self.pid = posix_spawnp(executable, args, sfa, env) self._child_created = True # parent 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)
def __execute(self, args, executable, preexec_fn, close_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, to_close=None): """Execute program using posix spawn""" if isinstance(args, (str, bytes)): args = [args] if shell: args = ["/bin/sh", "-c"] + args if executable == None: executable = args[0] sfa = SpawnFileAction() # Child file actions # Close parent's pipe ends closed_fds = [] if p2cwrite: sfa.add_close(p2cwrite) closed_fds.append(p2cwrite) if c2pread: sfa.add_close(c2pread) closed_fds.append(c2pread) if errread: sfa.add_close(errread) closed_fds.append(errread) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) if errwrite == 0 or errwrite == 1: errwrite = os.dup(errwrite) # Dup fds for child if p2cread: sfa.add_dup2(p2cread, 0) if c2pwrite: sfa.add_dup2(c2pwrite, 1) if errwrite: sfa.add_dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once. if p2cread: sfa.add_close(p2cread) closed_fds.append(p2cread) if c2pwrite and c2pwrite not in (p2cread,): sfa.add_close(c2pwrite) closed_fds.append(c2pwrite) if errwrite and errwrite not in (p2cread, c2pwrite): sfa.add_close(errwrite) closed_fds.append(errwrite) if cwd != None: os.chdir(cwd) if preexec_fn: preexec_fn() # Close all other fds, if asked for - after # preexec_fn(), which may open FDs. if close_fds: # # This is a bit tricky. Due to a sad # behaviour with posix_spawn in nevada # builds before the fix for 6807216 (in # nevada 110), (and perhaps on other OS's?) # you can't have two close actions close the # same FD, or an error results. So we track # everything we have closed, then manually # fstat and close up to the max we have # closed) . Then we close everything above # that efficiently with add_close_childfds(). # for i in range(3, max(closed_fds) + 1): # scheduled closed already? skip if i in closed_fds: continue try: os.fstat(i) sfa.add_close(i) closed_fds.append(i) except OSError: pass closefrom = max([3, max(closed_fds) + 1]) sfa.add_close_childfds(closefrom) if env is None: # If caller didn't pass us an environment in # env, borrow the env that the current process # is using. env = os.environ.copy() if type(env) == dict: # The bundled subprocess module takes a dict in # the "env" argument. Allow that here by doing # the explicit conversion to a list. env = [ "{0}={1}".format(k, v) for k, v in env.iteritems() ] self.pid = posix_spawnp(executable, args, sfa, env) self._child_created = True if to_close: def _close_in_parent(fd): os.close(fd) to_close.remove(fd) else: def _close_in_parent(fd): os.close(fd) # Parent if p2cread and p2cwrite: _close_in_parent(p2cread) if c2pwrite and c2pread: _close_in_parent(c2pwrite) if errwrite and errread: _close_in_parent(errwrite)