@@ -208,95 +208,108 @@ impl WebDriver {
208208
209209 fn spawn_process ( & self , driver_path : & Option < PathBuf > , port : u32 ) -> Result < Child > {
210210 let driver_path = driver_path. as_ref ( ) . unwrap ( ) ; // Safe unwrap since we validated above
211- let mut command = Command :: new ( driver_path) ;
212- command. arg ( format ! ( "--port={port}" ) ) ;
213-
214- // Add verbose flag only for chromedriver
215- #[ cfg( feature = "chromedriver" ) ]
216- command. arg ( "--verbose" ) ;
217-
218- command
219- . stdin ( Stdio :: piped ( ) )
220- . stdout ( Stdio :: piped ( ) )
221- . stderr ( Stdio :: piped ( ) ) ;
222-
223- info ! (
224- "Executing command: {:?} {:?}" ,
225- command. get_program( ) ,
226- command. get_args( )
227- ) ;
228-
229- #[ cfg( target_os = "windows" ) ]
230- {
231- use std:: os:: windows:: process:: CommandExt ;
232- // Try with CREATE_NO_WINDOW for headless operation
233- command. creation_flags ( 0x08000000 ) ; // CREATE_NO_WINDOW flag
234- }
211+
212+ let mut command = Self :: create_command ( driver_path, port) ;
213+ Self :: log_command ( & command) ;
235214
236- // Try to spawn the process
237215 match command. spawn ( ) {
238216 Ok ( child) => Ok ( child) ,
239217 Err ( e) => {
218+ #[ cfg( not( target_os = "windows" ) ) ]
219+ {
220+ Err ( self . handle_spawn_error ( e, & command, "standard method" ) )
221+ }
240222 #[ cfg( target_os = "windows" ) ]
241223 {
242224 // If CREATE_NO_WINDOW fails, try without any special flags
243225 error ! ( "Failed to spawn with CREATE_NO_WINDOW: {e}" ) ;
244226 error ! ( "Trying without special creation flags..." ) ;
245227
246- let mut fallback_command = Command :: new ( driver_path) ;
247- fallback_command. arg ( format ! ( "--port={port}" ) ) ;
248-
249- #[ cfg( feature = "chromedriver" ) ]
250- fallback_command. arg ( "--verbose" ) ;
251-
252- fallback_command
253- . stdin ( Stdio :: piped ( ) )
254- . stdout ( Stdio :: piped ( ) )
255- . stderr ( Stdio :: piped ( ) ) ;
228+ let fallback_command = Self :: standard_command ( driver_path, port) ;
229+ Self :: log_command ( & fallback_command) ;
256230
257231 match fallback_command. spawn ( ) {
258232 Ok ( child) => {
259233 info ! ( "Successfully spawned WebDriver without special creation flags" ) ;
260234 Ok ( child)
261235 }
262236 Err ( fallback_e) => {
263- error ! ( "Failed to spawn '{WEBDRIVER_BIN}' with fallback method: {fallback_e}" ) ;
264237 error ! ( "Original error: {e}" ) ;
265238 error ! ( "Fallback error: {fallback_e}" ) ;
266- error ! (
267- "Command was: {:?} {:?}" ,
268- command. get_program( ) ,
269- command. get_args( )
270- ) ;
271- error ! ( "Windows: Check if antivirus is blocking the process" ) ;
272- error ! ( "Windows: Check if the binary has proper permissions" ) ;
273- error ! (
274- "WebDriver diagnostics after spawn failure:\n {}" ,
275- self . get_diagnostics( )
276- ) ;
277- Err ( anyhow ! ( "Failed to spawn '{WEBDRIVER_BIN}': {}" , fallback_e) )
239+ Err ( self . handle_spawn_error ( fallback_e, & fallback_command, "fallback method" ) )
278240 }
279241 }
280242 }
281243
282- #[ cfg( not( target_os = "windows" ) ) ]
283- {
284- error ! ( "Failed to spawn '{WEBDRIVER_BIN}': {e}" ) ;
285- error ! (
286- "Command was: {:?} {:?}" ,
287- command. get_program( ) ,
288- command. get_args( )
289- ) ;
290- error ! (
291- "WebDriver diagnostics after spawn failure:\n {}" ,
292- self . get_diagnostics( )
293- ) ;
294- Err ( anyhow ! ( "Failed to spawn '{WEBDRIVER_BIN}': {}" , e) )
295- }
296244 }
297245 }
298246 }
299247
248+ /// Creates a command with standard configuration (no Windows flags)
249+ fn standard_command ( driver_path : & PathBuf , port : u32 ) -> Command {
250+ let mut command = Command :: new ( driver_path) ;
251+ command. arg ( format ! ( "--port={port}" ) ) ;
252+
253+ // Add verbose flag only for chromedriver
254+ #[ cfg( feature = "chromedriver" ) ]
255+ command. arg ( "--verbose" ) ;
256+
257+ command
258+ . stdin ( Stdio :: piped ( ) )
259+ . stdout ( Stdio :: piped ( ) )
260+ . stderr ( Stdio :: piped ( ) ) ;
261+
262+ command
263+ }
264+
265+ /// Creates a command with Windows-specific flags
266+ #[ cfg( target_os = "windows" ) ]
267+ fn create_command ( driver_path : & PathBuf , port : u32 ) -> Command {
268+ use std:: os:: windows:: process:: CommandExt ;
269+
270+ let mut command = Self :: standard_command ( driver_path, port) ;
271+ // Try with CREATE_NO_WINDOW for headless operation
272+ command. creation_flags ( 0x08000000 ) ; // CREATE_NO_WINDOW flag
273+ command
274+ }
275+
276+ #[ cfg( not( target_os = "windows" ) ) ]
277+ fn create_command ( driver_path : & PathBuf , port : u32 ) -> Command {
278+ Self :: standard_command ( driver_path, port)
279+ }
280+
281+ /// Logs command execution details
282+ fn log_command ( command : & Command ) {
283+ info ! (
284+ "Executing command: {:?} {:?}" ,
285+ command. get_program( ) ,
286+ command. get_args( )
287+ ) ;
288+ }
289+
290+ /// Handles spawn errors with appropriate logging and diagnostics
291+ fn handle_spawn_error ( & self , e : std:: io:: Error , command : & Command , attempt : & str ) -> anyhow:: Error {
292+ error ! ( "Failed to spawn '{WEBDRIVER_BIN}' with {attempt}: {e}" ) ;
293+ error ! (
294+ "Command was: {:?} {:?}" ,
295+ command. get_program( ) ,
296+ command. get_args( )
297+ ) ;
298+
299+ #[ cfg( target_os = "windows" ) ]
300+ if attempt == "CREATE_NO_WINDOW" {
301+ error ! ( "Windows: Check if antivirus is blocking the process" ) ;
302+ error ! ( "Windows: Check if the binary has proper permissions" ) ;
303+ }
304+
305+ error ! (
306+ "WebDriver diagnostics after spawn failure:\n {}" ,
307+ self . get_diagnostics( )
308+ ) ;
309+
310+ anyhow ! ( "Failed to spawn '{WEBDRIVER_BIN}': {}" , e)
311+ }
312+
300313 fn setup_output_monitoring ( & self , child : & mut Child , port : u32 ) {
301314 // Monitor stderr
302315 if let Some ( stderr) = child. stderr . take ( ) {
0 commit comments