symfony/process · error · LogicException

Cannot send signal on a non running process.

Error message

Cannot send signal on a non running process.

What it means

doSignal() needs the process PID to deliver a signal; if getPid() returns null the process is not running (never started or already terminated). With $throwException true it raises a LogicException instead of returning false.

Solutions

  1. Check $process->isRunning() before calling signal()
  2. Guard with start() first if the process was never started
  3. Use the non-throwing path ($throwException=false via stop(false)) when racing termination is expected

Example fix

// before
$process->signal(SIGTERM);
// after
if ($process->isRunning()) {
    $process->signal(SIGTERM);
}
Defensive patterns

Strategy: type-guard

Validate before calling

if ($process->isRunning()) {
    $process->signal(SIGTERM);
}

Type guard

function canSignal(Symfony\Component\Process\Process $p): bool { return $p->isRunning(); }

Try / catch

try { $process->signal($sig); } catch (LogicException $e) { /* process not running; ignore or restart */ }

Prevention

When it happens

Trigger: Calling $process->signal(SIGTERM) (or stop() with exceptions) on a process that was never started or has already exited.

Common situations: Signaling in a shutdown handler after the process already finished, signaling a freshly constructed Process, race where the child exited before signal() was reached.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

Thrown at Process.php:1529

     * Sends a POSIX signal to the process.
     *
     * @param int  $signal         A valid POSIX signal (see https://php.net/pcntl.constants)
     * @param bool $throwException Whether to throw exception in case signal failed
     *
     * @throws LogicException   In case the process is not running
     * @throws RuntimeException In case --enable-sigchild is activated and the process can't be killed
     * @throws RuntimeException In case of failure
     */
    private function doSignal(int $signal, bool $throwException): bool
    {
        // 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')) {

View on GitHub (pinned to 99b85026db)