diff options
| author | Devtools Arcadia <[email protected]> | 2022-02-07 18:08:42 +0300 | 
|---|---|---|
| committer | Devtools Arcadia <[email protected]> | 2022-02-07 18:08:42 +0300 | 
| commit | 1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch) | |
| tree | e26c9fed0de5d9873cce7e00bc214573dc2195b7 /contrib/tools/python3/src/Lib/multiprocessing/popen_forkserver.py | |
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'contrib/tools/python3/src/Lib/multiprocessing/popen_forkserver.py')
| -rw-r--r-- | contrib/tools/python3/src/Lib/multiprocessing/popen_forkserver.py | 74 | 
1 files changed, 74 insertions, 0 deletions
diff --git a/contrib/tools/python3/src/Lib/multiprocessing/popen_forkserver.py b/contrib/tools/python3/src/Lib/multiprocessing/popen_forkserver.py new file mode 100644 index 00000000000..a56eb9bf110 --- /dev/null +++ b/contrib/tools/python3/src/Lib/multiprocessing/popen_forkserver.py @@ -0,0 +1,74 @@ +import io +import os + +from .context import reduction, set_spawning_popen +if not reduction.HAVE_SEND_HANDLE: +    raise ImportError('No support for sending fds between processes') +from . import forkserver +from . import popen_fork +from . import spawn +from . import util + + +__all__ = ['Popen'] + +# +# Wrapper for an fd used while launching a process +# + +class _DupFd(object): +    def __init__(self, ind): +        self.ind = ind +    def detach(self): +        return forkserver.get_inherited_fds()[self.ind] + +# +# Start child process using a server process +# + +class Popen(popen_fork.Popen): +    method = 'forkserver' +    DupFd = _DupFd + +    def __init__(self, process_obj): +        self._fds = [] +        super().__init__(process_obj) + +    def duplicate_for_child(self, fd): +        self._fds.append(fd) +        return len(self._fds) - 1 + +    def _launch(self, process_obj): +        prep_data = spawn.get_preparation_data(process_obj._name) +        buf = io.BytesIO() +        set_spawning_popen(self) +        try: +            reduction.dump(prep_data, buf) +            reduction.dump(process_obj, buf) +        finally: +            set_spawning_popen(None) + +        self.sentinel, w = forkserver.connect_to_new_process(self._fds) +        # Keep a duplicate of the data pipe's write end as a sentinel of the +        # parent process used by the child process. +        _parent_w = os.dup(w) +        self.finalizer = util.Finalize(self, util.close_fds, +                                       (_parent_w, self.sentinel)) +        with open(w, 'wb', closefd=True) as f: +            f.write(buf.getbuffer()) +        self.pid = forkserver.read_signed(self.sentinel) + +    def poll(self, flag=os.WNOHANG): +        if self.returncode is None: +            from multiprocessing.connection import wait +            timeout = 0 if flag == os.WNOHANG else None +            if not wait([self.sentinel], timeout): +                return None +            try: +                self.returncode = forkserver.read_signed(self.sentinel) +            except (OSError, EOFError): +                # This should not happen usually, but perhaps the forkserver +                # process itself got killed +                self.returncode = 255 + +        return self.returncode  | 
