symfony/process · error · RuntimeException
Unable to kill the process
Error message
Unable to kill the process (%s).
What it means
On Windows, doSignal() kills via 'taskkill /F /T /PID'. If taskkill exits non-zero and the process still reports running, the kill failed and a RuntimeException with the taskkill output is thrown when $throwException is set.
Solutions
- Run the PHP process with sufficient privileges to terminate the target PID
- Retry the kill after a short delay and re-check isRunning()
- Catch RuntimeException and fall back to alternative termination (e.g. stop with a timeout, then SIGKILL path)
Example fix
// before
$process->stop(0, SIGKILL); // throws if taskkill fails
// after
try {
$process->stop(0, SIGKILL);
} catch (RuntimeException $e) {
// log $e->getMessage(); retry or escalate privileges
} Defensive patterns
Strategy: try-catch
Validate before calling
if ( stripos(PHP_OS, 'WIN') === 0 && $process->isRunning()) { /* proceed with kill */ } Try / catch
try { $process->stop(0, $sig); } catch (RuntimeException $e) { // taskkill failed
sleep(1); if ($process->isRunning()) { /* escalate/retry */ }
} Prevention
- Run PHP with privileges sufficient to kill child processes on Windows
- Test kill paths on Windows CI, not only Unix
- Verify ext behavior after OS/antivirus changes
When it happens
Trigger: Calling signal()/stop() on Windows where taskkill fails due to insufficient privileges, an already-exiting PID, or antivirus interference, while isRunning() still returns true.
Common situations: Windows CI runners or dev machines killing long-running children, processes running under a different user/elevated context, PID reuse races.
Related errors
- Error while sending signal
- A temporary file could not be opened to write the process…
- TTY mode is not supported on Windows platform.
- Invalid option " " passed to " ()". Supported options are "…
- Setting ignored signals while the process is running is not…
AI-assisted analysis of symfony/process@99b85026db (2026-09-14).
Data as JSON: /api/errors/15a84aa5ce7b848c.
Report an issue: GitHub.
Appendix: source
Thrown at Process.php:1539
{
// Signal seems to be send when sigchild is enable, this allow blocking the signal correctly in this case
if ($this->isSigchildEnabled() && \in_array($signal, $this->ignoredSignals)) {
return false;
}
if (null === $pid = $this->getPid()) {
if ($throwException) {
throw new LogicException('Cannot send signal on a non running process.');
}
return false;
}
if ('\\' === \DIRECTORY_SEPARATOR) {
exec(\sprintf('taskkill /F /T /PID %d 2>&1', $pid), $output, $exitCode);
if ($exitCode && $this->isRunning()) {
if ($throwException) {
throw new RuntimeException(\sprintf('Unable to kill the process (%s).', implode(' ', $output)));
}
return false;
}
} else {
if (!$this->isSigchildEnabled()) {
$ok = @proc_terminate($this->process, $signal);
} elseif (\function_exists('posix_kill')) {
$ok = @posix_kill($pid, $signal);
} elseif ($ok = proc_open(\sprintf('kill -%d %d', $signal, $pid), [2 => ['pipe', 'w']], $pipes)) {
$ok = false === fgets($pipes[2]);
}
if (!$ok) {
if ($throwException) {
throw new RuntimeException(\sprintf('Error while sending signal "%s".', $signal));
}
return false;View on GitHub (pinned to 99b85026db)