|
1 | 1 | from __future__ import annotations |
2 | 2 |
|
3 | | -import errno |
4 | 3 | import glob |
5 | 4 | import json |
6 | 5 | import os |
@@ -87,8 +86,8 @@ def launch(self, options: BrowserLaunchOptions | None = None) -> LaunchedBrowser |
87 | 86 | child_read, parent_write = os.pipe() |
88 | 87 | parent_read = _move_fd_if_needed(parent_read, {3, 4}) |
89 | 88 | parent_write = _move_fd_if_needed(parent_write, {3, 4}) |
90 | | - child_read = _move_fd_to(child_read, 3) |
91 | | - child_write = _move_fd_to(child_write, 4) |
| 89 | + child_read = _move_fd_if_needed(child_read, {3, 4}) |
| 90 | + child_write = _move_fd_if_needed(child_write, {3, 4}) |
92 | 91 | process = _spawn_chrome_with_pipe_fds(executable_path, args, child_read, child_write) |
93 | 92 | os.close(child_read) |
94 | 93 | os.close(child_write) |
@@ -220,33 +219,28 @@ def _move_fd_if_needed(fd: int, reserved: set[int]) -> int: |
220 | 219 | if fd not in reserved: |
221 | 220 | return fd |
222 | 221 | moved = os.dup(fd) |
| 222 | + while moved in reserved: |
| 223 | + next_fd = os.dup(fd) |
| 224 | + os.close(moved) |
| 225 | + moved = next_fd |
223 | 226 | os.close(fd) |
224 | 227 | return moved |
225 | 228 |
|
226 | 229 |
|
227 | | -def _move_fd_to(fd: int, target: int) -> int: |
228 | | - if fd == target: |
229 | | - return fd |
230 | | - deadline = time.monotonic() + 1 |
231 | | - while True: |
232 | | - try: |
233 | | - os.dup2(fd, target) |
234 | | - break |
235 | | - except OSError as error: |
236 | | - if error.errno != errno.EBUSY or time.monotonic() >= deadline: |
237 | | - raise |
238 | | - time.sleep(0.001) |
239 | | - os.close(fd) |
240 | | - return target |
241 | | - |
242 | | - |
243 | 230 | def _spawn_chrome_with_pipe_fds(executable_path: str, args: list[str], child_read: int, child_write: int) -> _ChromeProcess: |
| 231 | + def map_pipe_fds() -> None: |
| 232 | + os.dup2(child_read, 3) |
| 233 | + os.dup2(child_write, 4) |
| 234 | + os.close(child_read) |
| 235 | + os.close(child_write) |
| 236 | + |
244 | 237 | return subprocess.Popen( |
245 | 238 | [executable_path, *args], |
246 | 239 | stdin=subprocess.DEVNULL, |
247 | 240 | stdout=subprocess.DEVNULL, |
248 | 241 | stderr=subprocess.DEVNULL, |
249 | | - pass_fds=(child_read, child_write), |
| 242 | + close_fds=sys.platform.startswith("win"), |
| 243 | + preexec_fn=None if sys.platform.startswith("win") else map_pipe_fds, |
250 | 244 | start_new_session=not sys.platform.startswith("win"), |
251 | 245 | ) |
252 | 246 |
|
|
0 commit comments