Skip to content

Commit c45f9bb

Browse files
committed
refactor webdriver spawn function
Signed-off-by: Andrei Gherghescu <[email protected]>
1 parent 5ee9e7f commit c45f9bb

File tree

1 file changed

+94
-65
lines changed

1 file changed

+94
-65
lines changed

plotly_static/src/webdriver.rs

Lines changed: 94 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,56 @@ 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+
212+
let mut command = Self::create_command(driver_path, port);
213+
Self::log_command(&command);
214+
215+
match command.spawn() {
216+
Ok(child) => Ok(child),
217+
Err(e) => {
218+
#[cfg(not(target_os = "windows"))]
219+
{
220+
Err(self.handle_spawn_error(e, &command, "standard method"))
221+
}
222+
#[cfg(target_os = "windows")]
223+
{
224+
self.spawn_with_fallback(driver_path, port, e, &command)
225+
}
226+
}
227+
}
228+
}
229+
230+
/// Windows-specific fallback spawn method when CREATE_NO_WINDOW fails
231+
#[cfg(target_os = "windows")]
232+
fn spawn_with_fallback(
233+
&self,
234+
driver_path: &PathBuf,
235+
port: u32,
236+
original_error: std::io::Error,
237+
original_command: &Command,
238+
) -> Result<Child> {
239+
// If CREATE_NO_WINDOW fails, try without any special flags
240+
error!("Failed to spawn with CREATE_NO_WINDOW: {original_error}");
241+
error!("Trying without special creation flags...");
242+
243+
let mut fallback_command = Self::standard_command(driver_path, port);
244+
Self::log_command(&fallback_command);
245+
246+
match fallback_command.spawn() {
247+
Ok(child) => {
248+
info!("Successfully spawned WebDriver without special creation flags");
249+
Ok(child)
250+
}
251+
Err(fallback_e) => {
252+
error!("Original error: {original_error}");
253+
error!("Fallback error: {fallback_e}");
254+
Err(self.handle_spawn_error(fallback_e, &fallback_command, "fallback method"))
255+
}
256+
}
257+
}
258+
259+
/// Creates a command with standard configuration (no Windows flags)
260+
fn standard_command(driver_path: &PathBuf, port: u32) -> Command {
211261
let mut command = Command::new(driver_path);
212262
command.arg(format!("--port={port}"));
213263

@@ -220,81 +270,60 @@ impl WebDriver {
220270
.stdout(Stdio::piped())
221271
.stderr(Stdio::piped());
222272

273+
command
274+
}
275+
276+
/// Creates a command with Windows-specific flags
277+
#[cfg(target_os = "windows")]
278+
fn create_command(driver_path: &PathBuf, port: u32) -> Command {
279+
use std::os::windows::process::CommandExt;
280+
281+
let mut command = Self::standard_command(driver_path, port);
282+
// Try with CREATE_NO_WINDOW for headless operation
283+
command.creation_flags(0x08000000); // CREATE_NO_WINDOW flag
284+
command
285+
}
286+
287+
#[cfg(not(target_os = "windows"))]
288+
fn create_command(driver_path: &PathBuf, port: u32) -> Command {
289+
Self::standard_command(driver_path, port)
290+
}
291+
292+
/// Logs command execution details
293+
fn log_command(command: &Command) {
223294
info!(
224295
"Executing command: {:?} {:?}",
225296
command.get_program(),
226297
command.get_args()
227298
);
299+
}
300+
301+
/// Handles spawn errors with appropriate logging and diagnostics
302+
fn handle_spawn_error(
303+
&self,
304+
e: std::io::Error,
305+
command: &Command,
306+
attempt: &str,
307+
) -> anyhow::Error {
308+
error!("Failed to spawn '{WEBDRIVER_BIN}' with {attempt}: {e}");
309+
error!(
310+
"Command was: {:?} {:?}",
311+
command.get_program(),
312+
command.get_args()
313+
);
228314

229315
#[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
316+
if attempt == "CREATE_NO_WINDOW" {
317+
error!("Windows: Check if antivirus is blocking the process");
318+
error!("Windows: Check if the binary has proper permissions");
234319
}
235320

236-
// Try to spawn the process
237-
match command.spawn() {
238-
Ok(child) => Ok(child),
239-
Err(e) => {
240-
#[cfg(target_os = "windows")]
241-
{
242-
// If CREATE_NO_WINDOW fails, try without any special flags
243-
error!("Failed to spawn with CREATE_NO_WINDOW: {e}");
244-
error!("Trying without special creation flags...");
245-
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());
256-
257-
match fallback_command.spawn() {
258-
Ok(child) => {
259-
info!("Successfully spawned WebDriver without special creation flags");
260-
Ok(child)
261-
}
262-
Err(fallback_e) => {
263-
error!("Failed to spawn '{WEBDRIVER_BIN}' with fallback method: {fallback_e}");
264-
error!("Original error: {e}");
265-
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))
278-
}
279-
}
280-
}
321+
error!(
322+
"WebDriver diagnostics after spawn failure:\n{}",
323+
self.get_diagnostics()
324+
);
281325

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-
}
296-
}
297-
}
326+
anyhow!("Failed to spawn '{WEBDRIVER_BIN}': {}", e)
298327
}
299328

300329
fn setup_output_monitoring(&self, child: &mut Child, port: u32) {

0 commit comments

Comments
 (0)