Implementation:SeleniumHQ Selenium ExternalProcess
| Knowledge Sources | |
|---|---|
| Domains | WebDriver, Infrastructure |
| Last Updated | 2026-02-12 00:00 GMT |
Overview
ExternalProcess wraps Java's ProcessBuilder/Process with a builder pattern, managed output capture via a circular buffer, and graceful shutdown with timeout support.
Description
ExternalProcess is a class in the org.openqa.selenium.os package that provides a fluent builder API for constructing, starting, and managing external OS processes. The builder allows configuring the command, environment variables, working directory, output buffer size (default 32768 bytes), and an optional output copy stream. When started, it redirects stderr to stdout, spawns a daemon thread to continuously read process output into a CircularOutputStream (or ByteArrayOutputStream if buffer size is -1), and optionally copies to a secondary stream. The class provides methods to check if the process is alive, wait for completion with a timeout, retrieve captured output in any charset, and perform graceful shutdown that first attempts normal termination before escalating to forcible destruction. Process cleanup includes joining the output worker thread with timeouts to prevent resource leaks.
Usage
Use ExternalProcess when Selenium needs to launch and manage external processes such as browser drivers (ChromeDriver, GeckoDriver), Selenium Manager, or other command-line tools. It is the primary mechanism for OS process lifecycle management within the Selenium Java bindings.
Code Reference
Source Location
- Repository: SeleniumHQ_Selenium
- File: java/src/org/openqa/selenium/os/ExternalProcess.java
Signature
public class ExternalProcess {
public static Builder builder()
public ExternalProcess(Process process, OutputStream outputStream, Thread worker)
public String getOutput()
public String getOutput(Charset encoding)
public boolean isAlive()
public boolean waitFor(Duration duration) throws InterruptedException
public int exitValue()
public void shutdown()
public void shutdown(Duration timeout)
public static class Builder {
public Builder command(String executable, List<String> arguments)
public Builder command(List<String> command)
public Builder command(String... command)
public List<String> command()
public Builder environment(String name, String value)
public Map<String, String> environment()
public File directory()
public Builder directory(String directory)
public Builder directory(File directory)
public Builder copyOutputTo(OutputStream stream)
public Builder bufferSize(int toKeep)
public ExternalProcess start() throws UncheckedIOException
}
}
Import
import org.openqa.selenium.os.ExternalProcess;
I/O Contract
| Method | Input | Output | Description |
|---|---|---|---|
builder() |
none | Builder |
Creates a new builder instance to configure and start an external process. |
Builder.command(String, List<String>) |
executable: path to binary; arguments: argument list |
Builder |
Sets the command as executable plus arguments. |
Builder.command(String...) |
command: executable followed by arguments |
Builder |
Sets the command from varargs. |
Builder.environment(String, String) |
name: env var name; value: env var value |
Builder |
Sets or replaces an environment variable for the process. |
Builder.directory(String) |
directory: working directory path |
Builder |
Sets the working directory. |
Builder.copyOutputTo(OutputStream) |
stream: output destination |
Builder |
Configures a secondary stream to receive a copy of process output. |
Builder.bufferSize(int) |
toKeep: bytes to buffer (default 32768, -1 for unlimited) |
Builder |
Configures the circular buffer size for captured output. |
Builder.start() |
none | ExternalProcess |
Starts the process and output capture thread. Throws UncheckedIOException on failure. Destroys the process forcibly if thread setup fails.
|
getOutput() |
none | String -- last N bytes of combined stdout/stderr |
Returns captured output in the default charset. |
getOutput(Charset) |
encoding: desired charset |
String -- last N bytes of combined stdout/stderr |
Returns captured output in the specified charset. |
isAlive() |
none | boolean |
Returns true if the process is still running. |
waitFor(Duration) |
duration: max wait time |
boolean -- true if process exited within duration |
Waits for the process to exit. Also joins the output worker thread on success. |
exitValue() |
none | int -- exit code |
Returns the process exit code. Throws IllegalThreadStateException if still running.
|
shutdown() |
none | void | Graceful shutdown with a 4-second timeout before forcible destruction. |
shutdown(Duration) |
timeout: max time for graceful shutdown |
void | Attempts normal termination, then forcible destruction if the process does not exit within the timeout. Joins the worker thread afterward. |
Usage Examples
import org.openqa.selenium.os.ExternalProcess;
import java.time.Duration;
// Start a process using the builder
ExternalProcess process = ExternalProcess.builder()
.command("chromedriver", List.of("--port=9515"))
.environment("PATH", "/usr/local/bin:/usr/bin")
.directory("/tmp")
.copyOutputTo(System.out)
.bufferSize(65536)
.start();
// Check if the process is running
if (process.isAlive()) {
System.out.println("Process is running");
}
// Wait for the process to finish
boolean exited = process.waitFor(Duration.ofSeconds(30));
if (exited) {
System.out.println("Exit code: " + process.exitValue());
System.out.println("Output: " + process.getOutput());
}
// Graceful shutdown with custom timeout
process.shutdown(Duration.ofSeconds(10));
Related Pages
- SeleniumHQ_Selenium_ExecutableFinder -- Locates executables on the filesystem before launching with ExternalProcess
- SeleniumHQ_Selenium_PortProber -- Finds free ports for processes started by ExternalProcess