blob: 6b0a8d635feadb5f90f6de12b3157469e54be25b [file] [log] [blame]
Richard Oudkerk84ed9a62013-08-14 15:35:41 +01001import io
2import os
3
Richard Oudkerkb1694cf2013-10-16 16:41:56 +01004from . import context
Richard Oudkerk84ed9a62013-08-14 15:35:41 +01005from . import popen_fork
6from . import reduction
7from . import spawn
8from . import util
9
Richard Oudkerk84ed9a62013-08-14 15:35:41 +010010__all__ = ['Popen']
11
12
13#
14# Wrapper for an fd used while launching a process
15#
16
17class _DupFd(object):
18 def __init__(self, fd):
19 self.fd = fd
20 def detach(self):
21 return self.fd
22
23#
24# Start child process using a fresh interpreter
25#
26
27class Popen(popen_fork.Popen):
28 method = 'spawn'
29 DupFd = _DupFd
30
31 def __init__(self, process_obj):
32 self._fds = []
33 super().__init__(process_obj)
34
35 def duplicate_for_child(self, fd):
36 self._fds.append(fd)
37 return fd
38
39 def _launch(self, process_obj):
Richard Oudkerk7d2d43c2013-08-22 11:38:57 +010040 from . import semaphore_tracker
Richard Oudkerkb1694cf2013-10-16 16:41:56 +010041 tracker_fd = semaphore_tracker.getfd()
Richard Oudkerk84ed9a62013-08-14 15:35:41 +010042 self._fds.append(tracker_fd)
43 prep_data = spawn.get_preparation_data(process_obj._name)
44 fp = io.BytesIO()
Richard Oudkerkb1694cf2013-10-16 16:41:56 +010045 context.set_spawning_popen(self)
Richard Oudkerk84ed9a62013-08-14 15:35:41 +010046 try:
47 reduction.dump(prep_data, fp)
48 reduction.dump(process_obj, fp)
49 finally:
Richard Oudkerkb1694cf2013-10-16 16:41:56 +010050 context.set_spawning_popen(None)
Richard Oudkerk84ed9a62013-08-14 15:35:41 +010051
52 parent_r = child_w = child_r = parent_w = None
53 try:
Victor Stinnerdaf45552013-08-28 00:53:59 +020054 parent_r, child_w = os.pipe()
55 child_r, parent_w = os.pipe()
Richard Oudkerk7d2d43c2013-08-22 11:38:57 +010056 cmd = spawn.get_command_line(tracker_fd=tracker_fd,
57 pipe_handle=child_r)
Richard Oudkerk84ed9a62013-08-14 15:35:41 +010058 self._fds.extend([child_r, child_w])
59 self.pid = util.spawnv_passfds(spawn.get_executable(),
60 cmd, self._fds)
61 self.sentinel = parent_r
62 with open(parent_w, 'wb', closefd=False) as f:
63 f.write(fp.getbuffer())
64 finally:
65 if parent_r is not None:
66 util.Finalize(self, os.close, (parent_r,))
67 for fd in (child_r, child_w, parent_w):
68 if fd is not None:
69 os.close(fd)