SeleniumHQ/selenium · error · TimeoutError
-> #{@pid} still alive after #{timeout} seconds
Error message
-> #{@pid} still alive after #{timeout} seconds What it means
ChildProcess#poll_for_exit waits for a spawned child (e.g. driver/server process) to exit, polling at POLL_INTERVAL up to the timeout. If the process is still alive past end_time, it raises TimeoutError. This is the process-level companion to socket timeouts.
Source
Thrown at rb/lib/selenium/webdriver/common/child_process.rb:100
_, @status = waitpid2(@pid, Process::WNOHANG | Process::WUNTRACED) if @status.nil?
return false if @status.nil?
exit_code = @status.exitstatus || @status.termsig
WebDriver.logger.debug(" -> exit code is #{exit_code.inspect}", id: :process)
!!exit_code
rescue Errno::ECHILD, Errno::ESRCH
WebDriver.logger.debug(" -> process: #{@pid} already finished", id: :process)
true
end
def poll_for_exit(timeout)
WebDriver.logger.debug("Polling #{timeout} seconds for exit of #{@pid}", id: :process)
end_time = Time.now + timeout
sleep POLL_INTERVAL until exited? || Time.now > end_time
raise TimeoutError, " -> #{@pid} still alive after #{timeout} seconds" unless exited?
end
def wait
return if exited?
_, @status = waitpid2(@pid)
end
private
def terminate_and_wait_else_kill(timeout)
WebDriver.logger.debug("Sending TERM to process: #{@pid}", id: :process)
terminate(@pid)
poll_for_exit(timeout)
WebDriver.logger.debug(" -> stopped #{@pid}", id: :process)
rescue TimeoutError, Errno::EINVAL
WebDriver.logger.debug(" -> sending KILL to process: #{@pid}", id: :process)View on GitHub (pinned to aa36b38e69)
Solutions
- Increase the timeout passed to poll_for_exit / the managed process stop call.
- Ensure signals (TERM/KILL) reach the child; in containers run with a proper init (tini) or share the PID namespace correctly.
- Reap orphaned processes from prior runs before starting new ones.
- Investigate why the child ignores shutdown — capture its logs before killing.
Example fix
// before process.poll_for_exit(5) // after process.poll_for_exit(30)
Defensive patterns
Strategy: retry
Validate before calling
# No pre-check can force a child to exit; pick a timeout appropriate to the environment. timeout = ci? ? 60 : 10
Try / catch
begin
process.poll_for_exit(timeout)
rescue TimeoutError => e
warn "child alive after #{timeout}s: #{e.message}"
process.kill rescue nil
end Prevention
- Use a generous poll timeout on slow/CI hosts.
- Ensure containers forward signals (use tini/dumb-init or share PID namespace).
- Track spawned PIDs so you can force-kill on timeout.
- Reap orphaned driver/server processes between runs.
When it happens
Trigger: Calling process.poll_for_exit(timeout) (typically via stop/wait on a managed process) where the child does not terminate within the timeout — e.g. an unresponsive driver or server process that ignores SIGTERM.
Common situations: Driver/browser/server process hung, OS slow to deliver signals, too-small timeout on a loaded CI box, zombie processes, container not forwarding signals.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- remote server not ready in {} seconds
- remote server not stopped in #{@timeout} seconds
- unable to connect to #{@executable_path} #{@host}:#{@port}:
- unable to bind to locking port #{@port} within #{@timeout} s
- timed out after #{@timeout} seconds
AI-assisted analysis of SeleniumHQ/selenium@aa36b38e69 (2026-08-14).
Data as JSON: /api/errors/b7471e1cd0252fef.
Report an issue: GitHub.