Request forkserver to create a child process. Returns a pair of fds (status_r, data_w). The calling process can read the child process's pid and (eventually) its returncode from status_r. The calling process should write to data_w the pickled preparation and process
(self, fds)
| 91 | return self._inherited_fds |
| 92 | |
| 93 | def connect_to_new_process(self, fds): |
| 94 | '''Request forkserver to create a child process. |
| 95 | |
| 96 | Returns a pair of fds (status_r, data_w). The calling process can read |
| 97 | the child process's pid and (eventually) its returncode from status_r. |
| 98 | The calling process should write to data_w the pickled preparation and |
| 99 | process data. |
| 100 | ''' |
| 101 | self.ensure_running() |
| 102 | assert self._forkserver_authkey |
| 103 | if len(fds) + 4 >= MAXFDS_TO_SEND: |
| 104 | raise ValueError('too many fds') |
| 105 | with socket.socket(socket.AF_UNIX) as client: |
| 106 | client.connect(self._forkserver_address) |
| 107 | parent_r, child_w = os.pipe() |
| 108 | child_r, parent_w = os.pipe() |
| 109 | allfds = [child_r, child_w, self._forkserver_alive_fd, |
| 110 | resource_tracker.getfd()] |
| 111 | allfds += fds |
| 112 | try: |
| 113 | client.setblocking(True) |
| 114 | wrapped_client = connection.Connection(client.fileno()) |
| 115 | # The other side of this exchange happens in the child as |
| 116 | # implemented in main(). |
| 117 | try: |
| 118 | connection.answer_challenge( |
| 119 | wrapped_client, self._forkserver_authkey) |
| 120 | connection.deliver_challenge( |
| 121 | wrapped_client, self._forkserver_authkey) |
| 122 | except (EOFError, ConnectionError, BrokenPipeError) as exc: |
| 123 | if (self._preload_modules and |
| 124 | self._preload_on_error == 'fail'): |
| 125 | exc.add_note( |
| 126 | "Forkserver process may have crashed during module " |
| 127 | "preloading. Check stderr." |
| 128 | ) |
| 129 | raise |
| 130 | finally: |
| 131 | wrapped_client._detach() |
| 132 | del wrapped_client |
| 133 | reduction.sendfds(client, allfds) |
| 134 | return parent_r, parent_w |
| 135 | except: |
| 136 | os.close(parent_r) |
| 137 | os.close(parent_w) |
| 138 | raise |
| 139 | finally: |
| 140 | os.close(child_r) |
| 141 | os.close(child_w) |
| 142 | |
| 143 | def ensure_running(self): |
| 144 | '''Make sure that a fork server is running. |
no test coverage detected