symfony/process · error · RuntimeException

Error while sending signal

Error message

Error while sending signal "%s".

What it means

On POSIX systems doSignal() sends the signal via posix_kill or a 'kill' proc_open. If both fail (sigchild disabled and posix_kill returns false, or the kill command reported an error), a RuntimeException 'Error while sending signal "%s".' is thrown when $throwException is true.

Solutions

  1. Install/enable the ext-posix extension so posix_kill is used
  2. Check isRunning() before signaling to avoid signaling dead PIDs
  3. Catch RuntimeException and treat as best-effort termination

Example fix

// before
$process->signal(SIGTERM); // RuntimeException in minimal containers
// after
if ($process->isRunning()) {
    try {
        $process->signal(SIGTERM);
    } catch (RuntimeException $e) {
        // fallback: wait for exit or force stop
    }
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (!function_exists('posix_kill')) { /* sigchild environment: be prepared for fallback */ }
if (!$process->isRunning()) { return; }

Try / catch

try { $process->signal($sig); } catch (RuntimeException $e) { /* best-effort: log and wait for exit */ }

Prevention

When it happens

Trigger: Signaling a PID that just exited (ESRCH), running under an environment without the posix extension and without a working kill binary (sigchild environments), lacking permission for the target process.

Common situations: Docker minimal images without posix/procps, signaling as unprivileged user a process owned by another user, race where the child terminates before the signal arrives.

Related errors


AI-assisted analysis of symfony/process@99b85026db (2026-09-14). Data as JSON: /api/errors/3f3c96d80d8e1f9e. Report an issue: GitHub.

Appendix: source

Thrown at Process.php:1554

            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;
            }
        }

        $this->latestSignal = $signal;
        $this->fallbackStatus['signaled'] = true;
        $this->fallbackStatus['exitcode'] = -1;
        $this->fallbackStatus['termsig'] = $this->latestSignal;

        return true;
    }

    /**
     * @param string|list<string> $commandline
     */
    private function buildShellCommandline(string|array $commandline): string

View on GitHub (pinned to 99b85026db)