@@ -75,7 +75,8 @@ def launch(self, options: BrowserLaunchOptions | None = None) -> LaunchedBrowser
7575 default_headless = sys .platform .startswith ("linux" ) and not os .environ .get ("DISPLAY" )
7676 if merged .get ("headless" , default_headless ):
7777 args .append ("--headless=new" )
78- if merged .get ("sandbox" , False ) is False :
78+ default_sandbox = not sys .platform .startswith ("linux" )
79+ if merged .get ("sandbox" , default_sandbox ) is False :
7980 args .append ("--no-sandbox" )
8081 args .extend (list (merged .get ("args" ) or []))
8182 args .extend (list (merged .get ("extra_args" ) or []))
@@ -85,10 +86,8 @@ def launch(self, options: BrowserLaunchOptions | None = None) -> LaunchedBrowser
8586 child_read , parent_write = os .pipe ()
8687 parent_read = _move_fd_if_needed (parent_read , {3 , 4 })
8788 parent_write = _move_fd_if_needed (parent_write , {3 , 4 })
88- if child_read == 4 :
89- child_read = _move_fd_if_needed (child_read , {4 })
90- if child_write == 3 :
91- child_write = _move_fd_if_needed (child_write , {3 })
89+ child_read = _move_fd_to (child_read , 3 )
90+ child_write = _move_fd_to (child_write , 4 )
9291 process = _spawn_chrome_with_pipe_fds (executable_path , args , child_read , child_write )
9392 os .close (child_read )
9493 os .close (child_write )
@@ -224,61 +223,23 @@ def _move_fd_if_needed(fd: int, reserved: set[int]) -> int:
224223 return moved
225224
226225
227- class _SpawnedProcess :
228- def __init__ (self , pid : int ) -> None :
229- self .pid = pid
230- self .returncode : int | None = None
231-
232- def terminate (self ) -> None :
233- self ._signal (signal .SIGTERM )
234-
235- def kill (self ) -> None :
236- self ._signal (signal .SIGKILL )
237-
238- def wait (self , timeout : float | None = None ) -> int :
239- deadline = None if timeout is None else time .monotonic () + timeout
240- while True :
241- try :
242- waited_pid , status = os .waitpid (self .pid , os .WNOHANG )
243- except ChildProcessError :
244- if self .returncode is None :
245- self .returncode = 0
246- return self .returncode
247- if waited_pid == self .pid :
248- self .returncode = os .waitstatus_to_exitcode (status )
249- return self .returncode
250- if deadline is not None and time .monotonic () >= deadline :
251- assert timeout is not None
252- raise subprocess .TimeoutExpired ([str (self .pid )], timeout )
253- time .sleep (0.05 )
254-
255- def _signal (self , sig : int ) -> None :
256- if self .returncode is not None :
257- return
258- try :
259- os .kill (self .pid , sig )
260- except ProcessLookupError :
261- self .returncode = 0
226+ def _move_fd_to (fd : int , target : int ) -> int :
227+ if fd == target :
228+ return fd
229+ os .dup2 (fd , target )
230+ os .close (fd )
231+ return target
262232
263233
264234def _spawn_chrome_with_pipe_fds (executable_path : str , args : list [str ], child_read : int , child_write : int ) -> _ChromeProcess :
265- if not hasattr (os , "posix_spawn" ):
266- raise RuntimeError ("remote_debugging='pipe' requires os.posix_spawn support in the Python client." )
267- devnull = os .open (os .devnull , os .O_RDWR )
268- file_actions : list [tuple [int , int ] | tuple [int , int , int ]] = [
269- (os .POSIX_SPAWN_DUP2 , devnull , 0 ),
270- (os .POSIX_SPAWN_DUP2 , devnull , 1 ),
271- (os .POSIX_SPAWN_DUP2 , devnull , 2 ),
272- (os .POSIX_SPAWN_DUP2 , child_read , 3 ),
273- (os .POSIX_SPAWN_DUP2 , child_write , 4 ),
274- ]
275- for fd in {devnull , child_read , child_write } - {0 , 1 , 2 , 3 , 4 }:
276- file_actions .append ((os .POSIX_SPAWN_CLOSE , fd ))
277- try :
278- pid = os .posix_spawn (executable_path , [executable_path , * args ], os .environ , file_actions = file_actions , setsid = True )
279- return _SpawnedProcess (pid )
280- finally :
281- os .close (devnull )
235+ return subprocess .Popen (
236+ [executable_path , * args ],
237+ stdin = subprocess .DEVNULL ,
238+ stdout = subprocess .DEVNULL ,
239+ stderr = subprocess .DEVNULL ,
240+ pass_fds = (child_read , child_write ),
241+ start_new_session = not sys .platform .startswith ("win" ),
242+ )
282243
283244
284245class _ChromeProcess (Protocol ):
0 commit comments