mirror of
				https://github.com/python/cpython.git
				synced 2025-11-03 19:34:08 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			69 lines
		
	
	
	
		
			1.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			69 lines
		
	
	
	
		
			1.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
import io
 | 
						|
import os
 | 
						|
 | 
						|
from . import context
 | 
						|
from . import popen_fork
 | 
						|
from . import reduction
 | 
						|
from . import spawn
 | 
						|
from . import util
 | 
						|
 | 
						|
__all__ = ['Popen']
 | 
						|
 | 
						|
 | 
						|
#
 | 
						|
# Wrapper for an fd used while launching a process
 | 
						|
#
 | 
						|
 | 
						|
class _DupFd(object):
 | 
						|
    def __init__(self, fd):
 | 
						|
        self.fd = fd
 | 
						|
    def detach(self):
 | 
						|
        return self.fd
 | 
						|
 | 
						|
#
 | 
						|
# Start child process using a fresh interpreter
 | 
						|
#
 | 
						|
 | 
						|
class Popen(popen_fork.Popen):
 | 
						|
    method = 'spawn'
 | 
						|
    DupFd = _DupFd
 | 
						|
 | 
						|
    def __init__(self, process_obj):
 | 
						|
        self._fds = []
 | 
						|
        super().__init__(process_obj)
 | 
						|
 | 
						|
    def duplicate_for_child(self, fd):
 | 
						|
        self._fds.append(fd)
 | 
						|
        return fd
 | 
						|
 | 
						|
    def _launch(self, process_obj):
 | 
						|
        from . import semaphore_tracker
 | 
						|
        tracker_fd = semaphore_tracker.getfd()
 | 
						|
        self._fds.append(tracker_fd)
 | 
						|
        prep_data = spawn.get_preparation_data(process_obj._name)
 | 
						|
        fp = io.BytesIO()
 | 
						|
        context.set_spawning_popen(self)
 | 
						|
        try:
 | 
						|
            reduction.dump(prep_data, fp)
 | 
						|
            reduction.dump(process_obj, fp)
 | 
						|
        finally:
 | 
						|
            context.set_spawning_popen(None)
 | 
						|
 | 
						|
        parent_r = child_w = child_r = parent_w = None
 | 
						|
        try:
 | 
						|
            parent_r, child_w = os.pipe()
 | 
						|
            child_r, parent_w = os.pipe()
 | 
						|
            cmd = spawn.get_command_line(tracker_fd=tracker_fd,
 | 
						|
                                         pipe_handle=child_r)
 | 
						|
            self._fds.extend([child_r, child_w])
 | 
						|
            self.pid = util.spawnv_passfds(spawn.get_executable(),
 | 
						|
                                           cmd, self._fds)
 | 
						|
            self.sentinel = parent_r
 | 
						|
            with open(parent_w, 'wb', closefd=False) as f:
 | 
						|
                f.write(fp.getbuffer())
 | 
						|
        finally:
 | 
						|
            if parent_r is not None:
 | 
						|
                util.Finalize(self, os.close, (parent_r,))
 | 
						|
            for fd in (child_r, child_w, parent_w):
 | 
						|
                if fd is not None:
 | 
						|
                    os.close(fd)
 |