{"record":{"id":"58af61fd0b039492","repo":"symfony/process","slug":"cannot-send-signal-on-a-non-running-process","errorCode":null,"errorMessage":"Cannot send signal on a non running process.","messagePattern":"Cannot send signal on a non running process\\.","errorType":"exception","errorClass":"LogicException","httpStatus":null,"severity":"error","filePath":"Process.php","lineNumber":1529,"sourceCode":"     * Sends a POSIX signal to the process.\n     *\n     * @param int  $signal         A valid POSIX signal (see https://php.net/pcntl.constants)\n     * @param bool $throwException Whether to throw exception in case signal failed\n     *\n     * @throws LogicException   In case the process is not running\n     * @throws RuntimeException In case --enable-sigchild is activated and the process can't be killed\n     * @throws RuntimeException In case of failure\n     */\n    private function doSignal(int $signal, bool $throwException): bool\n    {\n        // Signal seems to be send when sigchild is enable, this allow blocking the signal correctly in this case\n        if ($this->isSigchildEnabled() && \\in_array($signal, $this->ignoredSignals)) {\n            return false;\n        }\n\n        if (null === $pid = $this->getPid()) {\n            if ($throwException) {\n                throw new LogicException('Cannot send signal on a non running process.');\n            }\n\n            return false;\n        }\n\n        if ('\\\\' === \\DIRECTORY_SEPARATOR) {\n            exec(\\sprintf('taskkill /F /T /PID %d 2>&1', $pid), $output, $exitCode);\n            if ($exitCode && $this->isRunning()) {\n                if ($throwException) {\n                    throw new RuntimeException(\\sprintf('Unable to kill the process (%s).', implode(' ', $output)));\n                }\n\n                return false;\n            }\n        } else {\n            if (!$this->isSigchildEnabled()) {\n                $ok = @proc_terminate($this->process, $signal);\n            } elseif (\\function_exists('posix_kill')) {","sourceCodeStart":1511,"sourceCodeEnd":1547,"githubUrl":"https://github.com/symfony/process/blob/99b85026db14a68f02c6f3eeb01a1170ca25c491/Process.php#L1511-L1547","documentation":"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.","triggerScenarios":"Calling $process->signal(SIGTERM) (or stop() with exceptions) on a process that was never started or has already exited.","commonSituations":"Signaling in a shutdown handler after the process already finished, signaling a freshly constructed Process, race where the child exited before signal() was reached.","solutions":["Check $process->isRunning() before calling signal()","Guard with start() first if the process was never started","Use the non-throwing path ($throwException=false via stop(false)) when racing termination is expected"],"exampleFix":"// before\n$process->signal(SIGTERM);\n// after\nif ($process->isRunning()) {\n    $process->signal(SIGTERM);\n}","handlingStrategy":"type-guard","validationCode":"if ($process->isRunning()) {\n    $process->signal(SIGTERM);\n}","typeGuard":"function canSignal(Symfony\\Component\\Process\\Process $p): bool { return $p->isRunning(); }","tryCatchPattern":"try { $process->signal($sig); } catch (LogicException $e) { /* process not running; ignore or restart */ }","preventionTips":["Always gate signal() behind isRunning()","Track process lifecycle state in your own wrapper","Expect races: child may exit between check and signal"],"tags":["php","process","signals","lifecycle"],"backgroundTag":"invalid-state-transition","analyzedSha":"99b85026db14a68f02c6f3eeb01a1170ca25c491","analyzedAt":"2026-09-14T11:23:33.683Z","contentChangedAt":"2026-09-14T11:23:33.683Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}