diff --git a/java/src/org/openqa/selenium/os/CommandLine.java b/java/src/org/openqa/selenium/os/CommandLine.java index 30727ec255718..f26889c48afa4 100644 --- a/java/src/org/openqa/selenium/os/CommandLine.java +++ b/java/src/org/openqa/selenium/os/CommandLine.java @@ -27,6 +27,7 @@ import java.io.File; import java.io.OutputStream; import java.util.Map; +import java.util.concurrent.TimeUnit; public class CommandLine { @@ -100,6 +101,10 @@ public void execute() { waitFor(); } + public boolean waitForProcessStarted(long duration, TimeUnit unit) { + return process.waitForProcessStarted(duration, unit); + } + public void waitFor() { try { process.waitFor(); diff --git a/java/src/org/openqa/selenium/os/OsProcess.java b/java/src/org/openqa/selenium/os/OsProcess.java index 3680b4b820613..9f4a01460a433 100644 --- a/java/src/org/openqa/selenium/os/OsProcess.java +++ b/java/src/org/openqa/selenium/os/OsProcess.java @@ -105,6 +105,10 @@ public void executeAsync() { } } + public boolean waitForProcessStarted(long duration, TimeUnit unit) { + return executeWatchdog.waitForProcessStarted(duration, unit); + } + private OutputStream getOutputStream() { return drainTo == null ? inputOut : new MultiOutputStream(inputOut, drainTo); @@ -112,18 +116,21 @@ private OutputStream getOutputStream() { public int destroy() { SeleniumWatchDog watchdog = executeWatchdog; - watchdog.waitForProcessStarted(); - // I literally have no idea why we don't try and kill the process nicely on Windows. If you do, - // answers on the back of a postcard to SeleniumHQ, please. - if (!Platform.getCurrent().is(WINDOWS)) { - watchdog.destroyProcess(); - watchdog.waitForTerminationAfterDestroy(2, SECONDS); - } + if (watchdog.waitForProcessStarted(2, TimeUnit.MINUTES)) { + // I literally have no idea why we don't try and kill the process nicely on Windows. If you do, + // answers on the back of a postcard to SeleniumHQ, please. + if (!Platform.getCurrent().is(WINDOWS)) { + watchdog.destroyProcess(); + watchdog.waitForTerminationAfterDestroy(2, SECONDS); + } - if (isRunning()) { - watchdog.destroyHarder(); - watchdog.waitForTerminationAfterDestroy(1, SECONDS); + if (isRunning()) { + watchdog.destroyHarder(); + watchdog.waitForTerminationAfterDestroy(1, SECONDS); + } + } else { + log.warning("Tried to destory a process which never started."); } // Make a best effort to drain the streams. @@ -236,8 +243,9 @@ public void reset() { starting = true; } - private void waitForProcessStarted() { - while (starting) { + private boolean waitForProcessStarted(long duration, TimeUnit unit) { + long end = System.currentTimeMillis() + unit.toMillis(duration); + while (starting && System.currentTimeMillis() < end) { try { Thread.sleep(50); } catch (InterruptedException e) { @@ -245,6 +253,8 @@ private void waitForProcessStarted() { throw new WebDriverException(e); } } + + return !starting; } private void waitForTerminationAfterDestroy(int duration, TimeUnit unit) { diff --git a/java/src/org/openqa/selenium/remote/service/DriverService.java b/java/src/org/openqa/selenium/remote/service/DriverService.java index f762d2cf9ce8f..26044b68b5dc0 100644 --- a/java/src/org/openqa/selenium/remote/service/DriverService.java +++ b/java/src/org/openqa/selenium/remote/service/DriverService.java @@ -213,6 +213,9 @@ public void start() throws IOException { process.setEnvironmentVariables(environment); process.copyOutputTo(getOutputStream()); process.executeAsync(); + if (!process.waitForProcessStarted(timeout.toMillis(), TimeUnit.MILLISECONDS)) { + throw new WebDriverException("Timed out waiting for driver process to start."); + } CompletableFuture serverStarted = CompletableFuture.supplyAsync(() -> { waitUntilAvailable(); @@ -231,13 +234,15 @@ public void start() throws IOException { try { StartOrDie status = (StartOrDie) CompletableFuture.anyOf(serverStarted, processFinished) .get(getTimeout().toMillis() * 2, TimeUnit.MILLISECONDS); - if (status == StartOrDie.SERVER_STARTED) { - processFinished.cancel(true); - } else { - if (status == StartOrDie.PROCESS_DIED) { + switch (status) { + case SERVER_STARTED: + processFinished.cancel(true); + break; + case PROCESS_DIED: process = null; throw new WebDriverException("Driver server process died prematurely."); - } + case PROCESS_IS_ACTIVE: + throw new WebDriverException("Timed out waiting for driver server to bind the port."); } } catch (ExecutionException | TimeoutException e) { throw new WebDriverException("Timed out waiting for driver server to start.", e);