17db96d56Sopenharmony_ciimport io
27db96d56Sopenharmony_ciimport os
37db96d56Sopenharmony_ci
47db96d56Sopenharmony_cifrom .context import reduction, set_spawning_popen
57db96d56Sopenharmony_cifrom . import popen_fork
67db96d56Sopenharmony_cifrom . import spawn
77db96d56Sopenharmony_cifrom . import util
87db96d56Sopenharmony_ci
97db96d56Sopenharmony_ci__all__ = ['Popen']
107db96d56Sopenharmony_ci
117db96d56Sopenharmony_ci
127db96d56Sopenharmony_ci#
137db96d56Sopenharmony_ci# Wrapper for an fd used while launching a process
147db96d56Sopenharmony_ci#
157db96d56Sopenharmony_ci
167db96d56Sopenharmony_ciclass _DupFd(object):
177db96d56Sopenharmony_ci    def __init__(self, fd):
187db96d56Sopenharmony_ci        self.fd = fd
197db96d56Sopenharmony_ci    def detach(self):
207db96d56Sopenharmony_ci        return self.fd
217db96d56Sopenharmony_ci
227db96d56Sopenharmony_ci#
237db96d56Sopenharmony_ci# Start child process using a fresh interpreter
247db96d56Sopenharmony_ci#
257db96d56Sopenharmony_ci
267db96d56Sopenharmony_ciclass Popen(popen_fork.Popen):
277db96d56Sopenharmony_ci    method = 'spawn'
287db96d56Sopenharmony_ci    DupFd = _DupFd
297db96d56Sopenharmony_ci
307db96d56Sopenharmony_ci    def __init__(self, process_obj):
317db96d56Sopenharmony_ci        self._fds = []
327db96d56Sopenharmony_ci        super().__init__(process_obj)
337db96d56Sopenharmony_ci
347db96d56Sopenharmony_ci    def duplicate_for_child(self, fd):
357db96d56Sopenharmony_ci        self._fds.append(fd)
367db96d56Sopenharmony_ci        return fd
377db96d56Sopenharmony_ci
387db96d56Sopenharmony_ci    def _launch(self, process_obj):
397db96d56Sopenharmony_ci        from . import resource_tracker
407db96d56Sopenharmony_ci        tracker_fd = resource_tracker.getfd()
417db96d56Sopenharmony_ci        self._fds.append(tracker_fd)
427db96d56Sopenharmony_ci        prep_data = spawn.get_preparation_data(process_obj._name)
437db96d56Sopenharmony_ci        fp = io.BytesIO()
447db96d56Sopenharmony_ci        set_spawning_popen(self)
457db96d56Sopenharmony_ci        try:
467db96d56Sopenharmony_ci            reduction.dump(prep_data, fp)
477db96d56Sopenharmony_ci            reduction.dump(process_obj, fp)
487db96d56Sopenharmony_ci        finally:
497db96d56Sopenharmony_ci            set_spawning_popen(None)
507db96d56Sopenharmony_ci
517db96d56Sopenharmony_ci        parent_r = child_w = child_r = parent_w = None
527db96d56Sopenharmony_ci        try:
537db96d56Sopenharmony_ci            parent_r, child_w = os.pipe()
547db96d56Sopenharmony_ci            child_r, parent_w = os.pipe()
557db96d56Sopenharmony_ci            cmd = spawn.get_command_line(tracker_fd=tracker_fd,
567db96d56Sopenharmony_ci                                         pipe_handle=child_r)
577db96d56Sopenharmony_ci            self._fds.extend([child_r, child_w])
587db96d56Sopenharmony_ci            self.pid = util.spawnv_passfds(spawn.get_executable(),
597db96d56Sopenharmony_ci                                           cmd, self._fds)
607db96d56Sopenharmony_ci            self.sentinel = parent_r
617db96d56Sopenharmony_ci            with open(parent_w, 'wb', closefd=False) as f:
627db96d56Sopenharmony_ci                f.write(fp.getbuffer())
637db96d56Sopenharmony_ci        finally:
647db96d56Sopenharmony_ci            fds_to_close = []
657db96d56Sopenharmony_ci            for fd in (parent_r, parent_w):
667db96d56Sopenharmony_ci                if fd is not None:
677db96d56Sopenharmony_ci                    fds_to_close.append(fd)
687db96d56Sopenharmony_ci            self.finalizer = util.Finalize(self, util.close_fds, fds_to_close)
697db96d56Sopenharmony_ci
707db96d56Sopenharmony_ci            for fd in (child_r, child_w):
717db96d56Sopenharmony_ci                if fd is not None:
727db96d56Sopenharmony_ci                    os.close(fd)
73