| 
									
										
										
										
											2013-08-14 15:35:41 +01:00
										 |  |  | import io | 
					
						
							|  |  |  | import os | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-09 18:03:10 -05:00
										 |  |  | from .context import reduction, set_spawning_popen | 
					
						
							| 
									
										
										
										
											2013-08-14 15:35:41 +01:00
										 |  |  | 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, 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): | 
					
						
							| 
									
										
										
										
											2019-05-10 22:59:08 +02:00
										 |  |  |         from . import resource_tracker | 
					
						
							|  |  |  |         tracker_fd = resource_tracker.getfd() | 
					
						
							| 
									
										
										
										
											2013-08-14 15:35:41 +01:00
										 |  |  |         self._fds.append(tracker_fd) | 
					
						
							|  |  |  |         prep_data = spawn.get_preparation_data(process_obj._name) | 
					
						
							|  |  |  |         fp = io.BytesIO() | 
					
						
							| 
									
										
										
										
											2016-09-09 18:03:10 -05:00
										 |  |  |         set_spawning_popen(self) | 
					
						
							| 
									
										
										
										
											2013-08-14 15:35:41 +01:00
										 |  |  |         try: | 
					
						
							|  |  |  |             reduction.dump(prep_data, fp) | 
					
						
							|  |  |  |             reduction.dump(process_obj, fp) | 
					
						
							|  |  |  |         finally: | 
					
						
							| 
									
										
										
										
											2016-09-09 18:03:10 -05:00
										 |  |  |             set_spawning_popen(None) | 
					
						
							| 
									
										
										
										
											2013-08-14 15:35:41 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         parent_r = child_w = child_r = parent_w = None | 
					
						
							|  |  |  |         try: | 
					
						
							| 
									
										
										
										
											2013-08-28 00:53:59 +02:00
										 |  |  |             parent_r, child_w = os.pipe() | 
					
						
							|  |  |  |             child_r, parent_w = os.pipe() | 
					
						
							| 
									
										
										
										
											2013-08-22 11:38:57 +01:00
										 |  |  |             cmd = spawn.get_command_line(tracker_fd=tracker_fd, | 
					
						
							|  |  |  |                                          pipe_handle=child_r) | 
					
						
							| 
									
										
										
										
											2013-08-14 15:35:41 +01:00
										 |  |  |             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: | 
					
						
							| 
									
										
										
										
											2019-05-20 21:37:05 +02:00
										 |  |  |             fds_to_close = [] | 
					
						
							|  |  |  |             for fd in (parent_r, parent_w): | 
					
						
							|  |  |  |                 if fd is not None: | 
					
						
							|  |  |  |                     fds_to_close.append(fd) | 
					
						
							|  |  |  |             self.finalizer = util.Finalize(self, util.close_fds, fds_to_close) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             for fd in (child_r, child_w): | 
					
						
							| 
									
										
										
										
											2013-08-14 15:35:41 +01:00
										 |  |  |                 if fd is not None: | 
					
						
							|  |  |  |                     os.close(fd) |