1*cda5da8dSAndroid Build Coastguard Workerimport errno 2*cda5da8dSAndroid Build Coastguard Workerimport os 3*cda5da8dSAndroid Build Coastguard Workerimport selectors 4*cda5da8dSAndroid Build Coastguard Workerimport signal 5*cda5da8dSAndroid Build Coastguard Workerimport socket 6*cda5da8dSAndroid Build Coastguard Workerimport struct 7*cda5da8dSAndroid Build Coastguard Workerimport sys 8*cda5da8dSAndroid Build Coastguard Workerimport threading 9*cda5da8dSAndroid Build Coastguard Workerimport warnings 10*cda5da8dSAndroid Build Coastguard Worker 11*cda5da8dSAndroid Build Coastguard Workerfrom . import connection 12*cda5da8dSAndroid Build Coastguard Workerfrom . import process 13*cda5da8dSAndroid Build Coastguard Workerfrom .context import reduction 14*cda5da8dSAndroid Build Coastguard Workerfrom . import resource_tracker 15*cda5da8dSAndroid Build Coastguard Workerfrom . import spawn 16*cda5da8dSAndroid Build Coastguard Workerfrom . import util 17*cda5da8dSAndroid Build Coastguard Worker 18*cda5da8dSAndroid Build Coastguard Worker__all__ = ['ensure_running', 'get_inherited_fds', 'connect_to_new_process', 19*cda5da8dSAndroid Build Coastguard Worker 'set_forkserver_preload'] 20*cda5da8dSAndroid Build Coastguard Worker 21*cda5da8dSAndroid Build Coastguard Worker# 22*cda5da8dSAndroid Build Coastguard Worker# 23*cda5da8dSAndroid Build Coastguard Worker# 24*cda5da8dSAndroid Build Coastguard Worker 25*cda5da8dSAndroid Build Coastguard WorkerMAXFDS_TO_SEND = 256 26*cda5da8dSAndroid Build Coastguard WorkerSIGNED_STRUCT = struct.Struct('q') # large enough for pid_t 27*cda5da8dSAndroid Build Coastguard Worker 28*cda5da8dSAndroid Build Coastguard Worker# 29*cda5da8dSAndroid Build Coastguard Worker# Forkserver class 30*cda5da8dSAndroid Build Coastguard Worker# 31*cda5da8dSAndroid Build Coastguard Worker 32*cda5da8dSAndroid Build Coastguard Workerclass ForkServer(object): 33*cda5da8dSAndroid Build Coastguard Worker 34*cda5da8dSAndroid Build Coastguard Worker def __init__(self): 35*cda5da8dSAndroid Build Coastguard Worker self._forkserver_address = None 36*cda5da8dSAndroid Build Coastguard Worker self._forkserver_alive_fd = None 37*cda5da8dSAndroid Build Coastguard Worker self._forkserver_pid = None 38*cda5da8dSAndroid Build Coastguard Worker self._inherited_fds = None 39*cda5da8dSAndroid Build Coastguard Worker self._lock = threading.Lock() 40*cda5da8dSAndroid Build Coastguard Worker self._preload_modules = ['__main__'] 41*cda5da8dSAndroid Build Coastguard Worker 42*cda5da8dSAndroid Build Coastguard Worker def _stop(self): 43*cda5da8dSAndroid Build Coastguard Worker # Method used by unit tests to stop the server 44*cda5da8dSAndroid Build Coastguard Worker with self._lock: 45*cda5da8dSAndroid Build Coastguard Worker self._stop_unlocked() 46*cda5da8dSAndroid Build Coastguard Worker 47*cda5da8dSAndroid Build Coastguard Worker def _stop_unlocked(self): 48*cda5da8dSAndroid Build Coastguard Worker if self._forkserver_pid is None: 49*cda5da8dSAndroid Build Coastguard Worker return 50*cda5da8dSAndroid Build Coastguard Worker 51*cda5da8dSAndroid Build Coastguard Worker # close the "alive" file descriptor asks the server to stop 52*cda5da8dSAndroid Build Coastguard Worker os.close(self._forkserver_alive_fd) 53*cda5da8dSAndroid Build Coastguard Worker self._forkserver_alive_fd = None 54*cda5da8dSAndroid Build Coastguard Worker 55*cda5da8dSAndroid Build Coastguard Worker os.waitpid(self._forkserver_pid, 0) 56*cda5da8dSAndroid Build Coastguard Worker self._forkserver_pid = None 57*cda5da8dSAndroid Build Coastguard Worker 58*cda5da8dSAndroid Build Coastguard Worker if not util.is_abstract_socket_namespace(self._forkserver_address): 59*cda5da8dSAndroid Build Coastguard Worker os.unlink(self._forkserver_address) 60*cda5da8dSAndroid Build Coastguard Worker self._forkserver_address = None 61*cda5da8dSAndroid Build Coastguard Worker 62*cda5da8dSAndroid Build Coastguard Worker def set_forkserver_preload(self, modules_names): 63*cda5da8dSAndroid Build Coastguard Worker '''Set list of module names to try to load in forkserver process.''' 64*cda5da8dSAndroid Build Coastguard Worker if not all(type(mod) is str for mod in self._preload_modules): 65*cda5da8dSAndroid Build Coastguard Worker raise TypeError('module_names must be a list of strings') 66*cda5da8dSAndroid Build Coastguard Worker self._preload_modules = modules_names 67*cda5da8dSAndroid Build Coastguard Worker 68*cda5da8dSAndroid Build Coastguard Worker def get_inherited_fds(self): 69*cda5da8dSAndroid Build Coastguard Worker '''Return list of fds inherited from parent process. 70*cda5da8dSAndroid Build Coastguard Worker 71*cda5da8dSAndroid Build Coastguard Worker This returns None if the current process was not started by fork 72*cda5da8dSAndroid Build Coastguard Worker server. 73*cda5da8dSAndroid Build Coastguard Worker ''' 74*cda5da8dSAndroid Build Coastguard Worker return self._inherited_fds 75*cda5da8dSAndroid Build Coastguard Worker 76*cda5da8dSAndroid Build Coastguard Worker def connect_to_new_process(self, fds): 77*cda5da8dSAndroid Build Coastguard Worker '''Request forkserver to create a child process. 78*cda5da8dSAndroid Build Coastguard Worker 79*cda5da8dSAndroid Build Coastguard Worker Returns a pair of fds (status_r, data_w). The calling process can read 80*cda5da8dSAndroid Build Coastguard Worker the child process's pid and (eventually) its returncode from status_r. 81*cda5da8dSAndroid Build Coastguard Worker The calling process should write to data_w the pickled preparation and 82*cda5da8dSAndroid Build Coastguard Worker process data. 83*cda5da8dSAndroid Build Coastguard Worker ''' 84*cda5da8dSAndroid Build Coastguard Worker self.ensure_running() 85*cda5da8dSAndroid Build Coastguard Worker if len(fds) + 4 >= MAXFDS_TO_SEND: 86*cda5da8dSAndroid Build Coastguard Worker raise ValueError('too many fds') 87*cda5da8dSAndroid Build Coastguard Worker with socket.socket(socket.AF_UNIX) as client: 88*cda5da8dSAndroid Build Coastguard Worker client.connect(self._forkserver_address) 89*cda5da8dSAndroid Build Coastguard Worker parent_r, child_w = os.pipe() 90*cda5da8dSAndroid Build Coastguard Worker child_r, parent_w = os.pipe() 91*cda5da8dSAndroid Build Coastguard Worker allfds = [child_r, child_w, self._forkserver_alive_fd, 92*cda5da8dSAndroid Build Coastguard Worker resource_tracker.getfd()] 93*cda5da8dSAndroid Build Coastguard Worker allfds += fds 94*cda5da8dSAndroid Build Coastguard Worker try: 95*cda5da8dSAndroid Build Coastguard Worker reduction.sendfds(client, allfds) 96*cda5da8dSAndroid Build Coastguard Worker return parent_r, parent_w 97*cda5da8dSAndroid Build Coastguard Worker except: 98*cda5da8dSAndroid Build Coastguard Worker os.close(parent_r) 99*cda5da8dSAndroid Build Coastguard Worker os.close(parent_w) 100*cda5da8dSAndroid Build Coastguard Worker raise 101*cda5da8dSAndroid Build Coastguard Worker finally: 102*cda5da8dSAndroid Build Coastguard Worker os.close(child_r) 103*cda5da8dSAndroid Build Coastguard Worker os.close(child_w) 104*cda5da8dSAndroid Build Coastguard Worker 105*cda5da8dSAndroid Build Coastguard Worker def ensure_running(self): 106*cda5da8dSAndroid Build Coastguard Worker '''Make sure that a fork server is running. 107*cda5da8dSAndroid Build Coastguard Worker 108*cda5da8dSAndroid Build Coastguard Worker This can be called from any process. Note that usually a child 109*cda5da8dSAndroid Build Coastguard Worker process will just reuse the forkserver started by its parent, so 110*cda5da8dSAndroid Build Coastguard Worker ensure_running() will do nothing. 111*cda5da8dSAndroid Build Coastguard Worker ''' 112*cda5da8dSAndroid Build Coastguard Worker with self._lock: 113*cda5da8dSAndroid Build Coastguard Worker resource_tracker.ensure_running() 114*cda5da8dSAndroid Build Coastguard Worker if self._forkserver_pid is not None: 115*cda5da8dSAndroid Build Coastguard Worker # forkserver was launched before, is it still running? 116*cda5da8dSAndroid Build Coastguard Worker pid, status = os.waitpid(self._forkserver_pid, os.WNOHANG) 117*cda5da8dSAndroid Build Coastguard Worker if not pid: 118*cda5da8dSAndroid Build Coastguard Worker # still alive 119*cda5da8dSAndroid Build Coastguard Worker return 120*cda5da8dSAndroid Build Coastguard Worker # dead, launch it again 121*cda5da8dSAndroid Build Coastguard Worker os.close(self._forkserver_alive_fd) 122*cda5da8dSAndroid Build Coastguard Worker self._forkserver_address = None 123*cda5da8dSAndroid Build Coastguard Worker self._forkserver_alive_fd = None 124*cda5da8dSAndroid Build Coastguard Worker self._forkserver_pid = None 125*cda5da8dSAndroid Build Coastguard Worker 126*cda5da8dSAndroid Build Coastguard Worker cmd = ('from multiprocessing.forkserver import main; ' + 127*cda5da8dSAndroid Build Coastguard Worker 'main(%d, %d, %r, **%r)') 128*cda5da8dSAndroid Build Coastguard Worker 129*cda5da8dSAndroid Build Coastguard Worker if self._preload_modules: 130*cda5da8dSAndroid Build Coastguard Worker desired_keys = {'main_path', 'sys_path'} 131*cda5da8dSAndroid Build Coastguard Worker data = spawn.get_preparation_data('ignore') 132*cda5da8dSAndroid Build Coastguard Worker data = {x: y for x, y in data.items() if x in desired_keys} 133*cda5da8dSAndroid Build Coastguard Worker else: 134*cda5da8dSAndroid Build Coastguard Worker data = {} 135*cda5da8dSAndroid Build Coastguard Worker 136*cda5da8dSAndroid Build Coastguard Worker with socket.socket(socket.AF_UNIX) as listener: 137*cda5da8dSAndroid Build Coastguard Worker address = connection.arbitrary_address('AF_UNIX') 138*cda5da8dSAndroid Build Coastguard Worker listener.bind(address) 139*cda5da8dSAndroid Build Coastguard Worker if not util.is_abstract_socket_namespace(address): 140*cda5da8dSAndroid Build Coastguard Worker os.chmod(address, 0o600) 141*cda5da8dSAndroid Build Coastguard Worker listener.listen() 142*cda5da8dSAndroid Build Coastguard Worker 143*cda5da8dSAndroid Build Coastguard Worker # all client processes own the write end of the "alive" pipe; 144*cda5da8dSAndroid Build Coastguard Worker # when they all terminate the read end becomes ready. 145*cda5da8dSAndroid Build Coastguard Worker alive_r, alive_w = os.pipe() 146*cda5da8dSAndroid Build Coastguard Worker try: 147*cda5da8dSAndroid Build Coastguard Worker fds_to_pass = [listener.fileno(), alive_r] 148*cda5da8dSAndroid Build Coastguard Worker cmd %= (listener.fileno(), alive_r, self._preload_modules, 149*cda5da8dSAndroid Build Coastguard Worker data) 150*cda5da8dSAndroid Build Coastguard Worker exe = spawn.get_executable() 151*cda5da8dSAndroid Build Coastguard Worker args = [exe] + util._args_from_interpreter_flags() 152*cda5da8dSAndroid Build Coastguard Worker args += ['-c', cmd] 153*cda5da8dSAndroid Build Coastguard Worker pid = util.spawnv_passfds(exe, args, fds_to_pass) 154*cda5da8dSAndroid Build Coastguard Worker except: 155*cda5da8dSAndroid Build Coastguard Worker os.close(alive_w) 156*cda5da8dSAndroid Build Coastguard Worker raise 157*cda5da8dSAndroid Build Coastguard Worker finally: 158*cda5da8dSAndroid Build Coastguard Worker os.close(alive_r) 159*cda5da8dSAndroid Build Coastguard Worker self._forkserver_address = address 160*cda5da8dSAndroid Build Coastguard Worker self._forkserver_alive_fd = alive_w 161*cda5da8dSAndroid Build Coastguard Worker self._forkserver_pid = pid 162*cda5da8dSAndroid Build Coastguard Worker 163*cda5da8dSAndroid Build Coastguard Worker# 164*cda5da8dSAndroid Build Coastguard Worker# 165*cda5da8dSAndroid Build Coastguard Worker# 166*cda5da8dSAndroid Build Coastguard Worker 167*cda5da8dSAndroid Build Coastguard Workerdef main(listener_fd, alive_r, preload, main_path=None, sys_path=None): 168*cda5da8dSAndroid Build Coastguard Worker '''Run forkserver.''' 169*cda5da8dSAndroid Build Coastguard Worker if preload: 170*cda5da8dSAndroid Build Coastguard Worker if '__main__' in preload and main_path is not None: 171*cda5da8dSAndroid Build Coastguard Worker process.current_process()._inheriting = True 172*cda5da8dSAndroid Build Coastguard Worker try: 173*cda5da8dSAndroid Build Coastguard Worker spawn.import_main_path(main_path) 174*cda5da8dSAndroid Build Coastguard Worker finally: 175*cda5da8dSAndroid Build Coastguard Worker del process.current_process()._inheriting 176*cda5da8dSAndroid Build Coastguard Worker for modname in preload: 177*cda5da8dSAndroid Build Coastguard Worker try: 178*cda5da8dSAndroid Build Coastguard Worker __import__(modname) 179*cda5da8dSAndroid Build Coastguard Worker except ImportError: 180*cda5da8dSAndroid Build Coastguard Worker pass 181*cda5da8dSAndroid Build Coastguard Worker 182*cda5da8dSAndroid Build Coastguard Worker util._close_stdin() 183*cda5da8dSAndroid Build Coastguard Worker 184*cda5da8dSAndroid Build Coastguard Worker sig_r, sig_w = os.pipe() 185*cda5da8dSAndroid Build Coastguard Worker os.set_blocking(sig_r, False) 186*cda5da8dSAndroid Build Coastguard Worker os.set_blocking(sig_w, False) 187*cda5da8dSAndroid Build Coastguard Worker 188*cda5da8dSAndroid Build Coastguard Worker def sigchld_handler(*_unused): 189*cda5da8dSAndroid Build Coastguard Worker # Dummy signal handler, doesn't do anything 190*cda5da8dSAndroid Build Coastguard Worker pass 191*cda5da8dSAndroid Build Coastguard Worker 192*cda5da8dSAndroid Build Coastguard Worker handlers = { 193*cda5da8dSAndroid Build Coastguard Worker # unblocking SIGCHLD allows the wakeup fd to notify our event loop 194*cda5da8dSAndroid Build Coastguard Worker signal.SIGCHLD: sigchld_handler, 195*cda5da8dSAndroid Build Coastguard Worker # protect the process from ^C 196*cda5da8dSAndroid Build Coastguard Worker signal.SIGINT: signal.SIG_IGN, 197*cda5da8dSAndroid Build Coastguard Worker } 198*cda5da8dSAndroid Build Coastguard Worker old_handlers = {sig: signal.signal(sig, val) 199*cda5da8dSAndroid Build Coastguard Worker for (sig, val) in handlers.items()} 200*cda5da8dSAndroid Build Coastguard Worker 201*cda5da8dSAndroid Build Coastguard Worker # calling os.write() in the Python signal handler is racy 202*cda5da8dSAndroid Build Coastguard Worker signal.set_wakeup_fd(sig_w) 203*cda5da8dSAndroid Build Coastguard Worker 204*cda5da8dSAndroid Build Coastguard Worker # map child pids to client fds 205*cda5da8dSAndroid Build Coastguard Worker pid_to_fd = {} 206*cda5da8dSAndroid Build Coastguard Worker 207*cda5da8dSAndroid Build Coastguard Worker with socket.socket(socket.AF_UNIX, fileno=listener_fd) as listener, \ 208*cda5da8dSAndroid Build Coastguard Worker selectors.DefaultSelector() as selector: 209*cda5da8dSAndroid Build Coastguard Worker _forkserver._forkserver_address = listener.getsockname() 210*cda5da8dSAndroid Build Coastguard Worker 211*cda5da8dSAndroid Build Coastguard Worker selector.register(listener, selectors.EVENT_READ) 212*cda5da8dSAndroid Build Coastguard Worker selector.register(alive_r, selectors.EVENT_READ) 213*cda5da8dSAndroid Build Coastguard Worker selector.register(sig_r, selectors.EVENT_READ) 214*cda5da8dSAndroid Build Coastguard Worker 215*cda5da8dSAndroid Build Coastguard Worker while True: 216*cda5da8dSAndroid Build Coastguard Worker try: 217*cda5da8dSAndroid Build Coastguard Worker while True: 218*cda5da8dSAndroid Build Coastguard Worker rfds = [key.fileobj for (key, events) in selector.select()] 219*cda5da8dSAndroid Build Coastguard Worker if rfds: 220*cda5da8dSAndroid Build Coastguard Worker break 221*cda5da8dSAndroid Build Coastguard Worker 222*cda5da8dSAndroid Build Coastguard Worker if alive_r in rfds: 223*cda5da8dSAndroid Build Coastguard Worker # EOF because no more client processes left 224*cda5da8dSAndroid Build Coastguard Worker assert os.read(alive_r, 1) == b'', "Not at EOF?" 225*cda5da8dSAndroid Build Coastguard Worker raise SystemExit 226*cda5da8dSAndroid Build Coastguard Worker 227*cda5da8dSAndroid Build Coastguard Worker if sig_r in rfds: 228*cda5da8dSAndroid Build Coastguard Worker # Got SIGCHLD 229*cda5da8dSAndroid Build Coastguard Worker os.read(sig_r, 65536) # exhaust 230*cda5da8dSAndroid Build Coastguard Worker while True: 231*cda5da8dSAndroid Build Coastguard Worker # Scan for child processes 232*cda5da8dSAndroid Build Coastguard Worker try: 233*cda5da8dSAndroid Build Coastguard Worker pid, sts = os.waitpid(-1, os.WNOHANG) 234*cda5da8dSAndroid Build Coastguard Worker except ChildProcessError: 235*cda5da8dSAndroid Build Coastguard Worker break 236*cda5da8dSAndroid Build Coastguard Worker if pid == 0: 237*cda5da8dSAndroid Build Coastguard Worker break 238*cda5da8dSAndroid Build Coastguard Worker child_w = pid_to_fd.pop(pid, None) 239*cda5da8dSAndroid Build Coastguard Worker if child_w is not None: 240*cda5da8dSAndroid Build Coastguard Worker returncode = os.waitstatus_to_exitcode(sts) 241*cda5da8dSAndroid Build Coastguard Worker 242*cda5da8dSAndroid Build Coastguard Worker # Send exit code to client process 243*cda5da8dSAndroid Build Coastguard Worker try: 244*cda5da8dSAndroid Build Coastguard Worker write_signed(child_w, returncode) 245*cda5da8dSAndroid Build Coastguard Worker except BrokenPipeError: 246*cda5da8dSAndroid Build Coastguard Worker # client vanished 247*cda5da8dSAndroid Build Coastguard Worker pass 248*cda5da8dSAndroid Build Coastguard Worker os.close(child_w) 249*cda5da8dSAndroid Build Coastguard Worker else: 250*cda5da8dSAndroid Build Coastguard Worker # This shouldn't happen really 251*cda5da8dSAndroid Build Coastguard Worker warnings.warn('forkserver: waitpid returned ' 252*cda5da8dSAndroid Build Coastguard Worker 'unexpected pid %d' % pid) 253*cda5da8dSAndroid Build Coastguard Worker 254*cda5da8dSAndroid Build Coastguard Worker if listener in rfds: 255*cda5da8dSAndroid Build Coastguard Worker # Incoming fork request 256*cda5da8dSAndroid Build Coastguard Worker with listener.accept()[0] as s: 257*cda5da8dSAndroid Build Coastguard Worker # Receive fds from client 258*cda5da8dSAndroid Build Coastguard Worker fds = reduction.recvfds(s, MAXFDS_TO_SEND + 1) 259*cda5da8dSAndroid Build Coastguard Worker if len(fds) > MAXFDS_TO_SEND: 260*cda5da8dSAndroid Build Coastguard Worker raise RuntimeError( 261*cda5da8dSAndroid Build Coastguard Worker "Too many ({0:n}) fds to send".format( 262*cda5da8dSAndroid Build Coastguard Worker len(fds))) 263*cda5da8dSAndroid Build Coastguard Worker child_r, child_w, *fds = fds 264*cda5da8dSAndroid Build Coastguard Worker s.close() 265*cda5da8dSAndroid Build Coastguard Worker pid = os.fork() 266*cda5da8dSAndroid Build Coastguard Worker if pid == 0: 267*cda5da8dSAndroid Build Coastguard Worker # Child 268*cda5da8dSAndroid Build Coastguard Worker code = 1 269*cda5da8dSAndroid Build Coastguard Worker try: 270*cda5da8dSAndroid Build Coastguard Worker listener.close() 271*cda5da8dSAndroid Build Coastguard Worker selector.close() 272*cda5da8dSAndroid Build Coastguard Worker unused_fds = [alive_r, child_w, sig_r, sig_w] 273*cda5da8dSAndroid Build Coastguard Worker unused_fds.extend(pid_to_fd.values()) 274*cda5da8dSAndroid Build Coastguard Worker code = _serve_one(child_r, fds, 275*cda5da8dSAndroid Build Coastguard Worker unused_fds, 276*cda5da8dSAndroid Build Coastguard Worker old_handlers) 277*cda5da8dSAndroid Build Coastguard Worker except Exception: 278*cda5da8dSAndroid Build Coastguard Worker sys.excepthook(*sys.exc_info()) 279*cda5da8dSAndroid Build Coastguard Worker sys.stderr.flush() 280*cda5da8dSAndroid Build Coastguard Worker finally: 281*cda5da8dSAndroid Build Coastguard Worker os._exit(code) 282*cda5da8dSAndroid Build Coastguard Worker else: 283*cda5da8dSAndroid Build Coastguard Worker # Send pid to client process 284*cda5da8dSAndroid Build Coastguard Worker try: 285*cda5da8dSAndroid Build Coastguard Worker write_signed(child_w, pid) 286*cda5da8dSAndroid Build Coastguard Worker except BrokenPipeError: 287*cda5da8dSAndroid Build Coastguard Worker # client vanished 288*cda5da8dSAndroid Build Coastguard Worker pass 289*cda5da8dSAndroid Build Coastguard Worker pid_to_fd[pid] = child_w 290*cda5da8dSAndroid Build Coastguard Worker os.close(child_r) 291*cda5da8dSAndroid Build Coastguard Worker for fd in fds: 292*cda5da8dSAndroid Build Coastguard Worker os.close(fd) 293*cda5da8dSAndroid Build Coastguard Worker 294*cda5da8dSAndroid Build Coastguard Worker except OSError as e: 295*cda5da8dSAndroid Build Coastguard Worker if e.errno != errno.ECONNABORTED: 296*cda5da8dSAndroid Build Coastguard Worker raise 297*cda5da8dSAndroid Build Coastguard Worker 298*cda5da8dSAndroid Build Coastguard Worker 299*cda5da8dSAndroid Build Coastguard Workerdef _serve_one(child_r, fds, unused_fds, handlers): 300*cda5da8dSAndroid Build Coastguard Worker # close unnecessary stuff and reset signal handlers 301*cda5da8dSAndroid Build Coastguard Worker signal.set_wakeup_fd(-1) 302*cda5da8dSAndroid Build Coastguard Worker for sig, val in handlers.items(): 303*cda5da8dSAndroid Build Coastguard Worker signal.signal(sig, val) 304*cda5da8dSAndroid Build Coastguard Worker for fd in unused_fds: 305*cda5da8dSAndroid Build Coastguard Worker os.close(fd) 306*cda5da8dSAndroid Build Coastguard Worker 307*cda5da8dSAndroid Build Coastguard Worker (_forkserver._forkserver_alive_fd, 308*cda5da8dSAndroid Build Coastguard Worker resource_tracker._resource_tracker._fd, 309*cda5da8dSAndroid Build Coastguard Worker *_forkserver._inherited_fds) = fds 310*cda5da8dSAndroid Build Coastguard Worker 311*cda5da8dSAndroid Build Coastguard Worker # Run process object received over pipe 312*cda5da8dSAndroid Build Coastguard Worker parent_sentinel = os.dup(child_r) 313*cda5da8dSAndroid Build Coastguard Worker code = spawn._main(child_r, parent_sentinel) 314*cda5da8dSAndroid Build Coastguard Worker 315*cda5da8dSAndroid Build Coastguard Worker return code 316*cda5da8dSAndroid Build Coastguard Worker 317*cda5da8dSAndroid Build Coastguard Worker 318*cda5da8dSAndroid Build Coastguard Worker# 319*cda5da8dSAndroid Build Coastguard Worker# Read and write signed numbers 320*cda5da8dSAndroid Build Coastguard Worker# 321*cda5da8dSAndroid Build Coastguard Worker 322*cda5da8dSAndroid Build Coastguard Workerdef read_signed(fd): 323*cda5da8dSAndroid Build Coastguard Worker data = b'' 324*cda5da8dSAndroid Build Coastguard Worker length = SIGNED_STRUCT.size 325*cda5da8dSAndroid Build Coastguard Worker while len(data) < length: 326*cda5da8dSAndroid Build Coastguard Worker s = os.read(fd, length - len(data)) 327*cda5da8dSAndroid Build Coastguard Worker if not s: 328*cda5da8dSAndroid Build Coastguard Worker raise EOFError('unexpected EOF') 329*cda5da8dSAndroid Build Coastguard Worker data += s 330*cda5da8dSAndroid Build Coastguard Worker return SIGNED_STRUCT.unpack(data)[0] 331*cda5da8dSAndroid Build Coastguard Worker 332*cda5da8dSAndroid Build Coastguard Workerdef write_signed(fd, n): 333*cda5da8dSAndroid Build Coastguard Worker msg = SIGNED_STRUCT.pack(n) 334*cda5da8dSAndroid Build Coastguard Worker while msg: 335*cda5da8dSAndroid Build Coastguard Worker nbytes = os.write(fd, msg) 336*cda5da8dSAndroid Build Coastguard Worker if nbytes == 0: 337*cda5da8dSAndroid Build Coastguard Worker raise RuntimeError('should not get here') 338*cda5da8dSAndroid Build Coastguard Worker msg = msg[nbytes:] 339*cda5da8dSAndroid Build Coastguard Worker 340*cda5da8dSAndroid Build Coastguard Worker# 341*cda5da8dSAndroid Build Coastguard Worker# 342*cda5da8dSAndroid Build Coastguard Worker# 343*cda5da8dSAndroid Build Coastguard Worker 344*cda5da8dSAndroid Build Coastguard Worker_forkserver = ForkServer() 345*cda5da8dSAndroid Build Coastguard Workerensure_running = _forkserver.ensure_running 346*cda5da8dSAndroid Build Coastguard Workerget_inherited_fds = _forkserver.get_inherited_fds 347*cda5da8dSAndroid Build Coastguard Workerconnect_to_new_process = _forkserver.connect_to_new_process 348*cda5da8dSAndroid Build Coastguard Workerset_forkserver_preload = _forkserver.set_forkserver_preload 349