Make sure that a fork server is running. This can be called from any process. Note that usually a child process will just reuse the forkserver started by its parent, so ensure_running() will do nothing.
(self)
| 141 | os.close(child_w) |
| 142 | |
| 143 | def ensure_running(self): |
| 144 | '''Make sure that a fork server is running. |
| 145 | |
| 146 | This can be called from any process. Note that usually a child |
| 147 | process will just reuse the forkserver started by its parent, so |
| 148 | ensure_running() will do nothing. |
| 149 | ''' |
| 150 | with self._lock: |
| 151 | resource_tracker.ensure_running() |
| 152 | if self._forkserver_pid is not None: |
| 153 | # forkserver was launched before, is it still running? |
| 154 | pid, status = os.waitpid(self._forkserver_pid, os.WNOHANG) |
| 155 | if not pid: |
| 156 | # still alive |
| 157 | return |
| 158 | # dead, launch it again |
| 159 | os.close(self._forkserver_alive_fd) |
| 160 | self._forkserver_authkey = None |
| 161 | self._forkserver_address = None |
| 162 | self._forkserver_alive_fd = None |
| 163 | self._forkserver_pid = None |
| 164 | |
| 165 | # gh-144503: sys_argv is passed as real argv elements after the |
| 166 | # ``-c cmd`` rather than repr'd into main_kws so that a large |
| 167 | # parent sys.argv cannot push the single ``-c`` command string |
| 168 | # over the OS per-argument length limit (MAX_ARG_STRLEN on Linux). |
| 169 | # The child sees them as sys.argv[1:]. |
| 170 | cmd = ('import sys; ' |
| 171 | 'from multiprocessing.forkserver import main; ' |
| 172 | 'main(%d, %d, %r, sys_argv=sys.argv[1:], **%r)') |
| 173 | |
| 174 | main_kws = {} |
| 175 | sys_argv = None |
| 176 | if self._preload_modules: |
| 177 | data = spawn.get_preparation_data('ignore') |
| 178 | if 'sys_path' in data: |
| 179 | main_kws['sys_path'] = data['sys_path'] |
| 180 | if 'init_main_from_path' in data: |
| 181 | main_kws['main_path'] = data['init_main_from_path'] |
| 182 | if 'sys_argv' in data: |
| 183 | sys_argv = data['sys_argv'] |
| 184 | if self._preload_on_error != 'ignore': |
| 185 | main_kws['on_error'] = self._preload_on_error |
| 186 | |
| 187 | with socket.socket(socket.AF_UNIX) as listener: |
| 188 | address = connection.arbitrary_address('AF_UNIX') |
| 189 | listener.bind(address) |
| 190 | if not util.is_abstract_socket_namespace(address): |
| 191 | os.chmod(address, 0o600) |
| 192 | listener.listen() |
| 193 | |
| 194 | # all client processes own the write end of the "alive" pipe; |
| 195 | # when they all terminate the read end becomes ready. |
| 196 | alive_r, alive_w = os.pipe() |
| 197 | # A short lived pipe to initialize the forkserver authkey. |
| 198 | authkey_r, authkey_w = os.pipe() |
| 199 | try: |
| 200 | fds_to_pass = [listener.fileno(), alive_r, authkey_r] |