{"record":{"id":"15a84aa5ce7b848c","repo":"symfony/process","slug":"unable-to-kill-the-process-s","errorCode":null,"errorMessage":"Unable to kill the process (%s).","messagePattern":"Unable to kill the process \\((.+?)\\)\\.","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"Process.php","lineNumber":1539,"sourceCode":"    {\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')) {\n                $ok = @posix_kill($pid, $signal);\n            } elseif ($ok = proc_open(\\sprintf('kill -%d %d', $signal, $pid), [2 => ['pipe', 'w']], $pipes)) {\n                $ok = false === fgets($pipes[2]);\n            }\n            if (!$ok) {\n                if ($throwException) {\n                    throw new RuntimeException(\\sprintf('Error while sending signal \"%s\".', $signal));\n                }\n\n                return false;","sourceCodeStart":1521,"sourceCodeEnd":1557,"githubUrl":"https://github.com/symfony/process/blob/99b85026db14a68f02c6f3eeb01a1170ca25c491/Process.php#L1521-L1557","documentation":"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.","triggerScenarios":"Calling signal()/stop() on Windows where taskkill fails due to insufficient privileges, an already-exiting PID, or antivirus interference, while isRunning() still returns true.","commonSituations":"Windows CI runners or dev machines killing long-running children, processes running under a different user/elevated context, PID reuse races.","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)"],"exampleFix":"// before\n$process->stop(0, SIGKILL); // throws if taskkill fails\n// after\ntry {\n    $process->stop(0, SIGKILL);\n} catch (RuntimeException $e) {\n    // log $e->getMessage(); retry or escalate privileges\n}","handlingStrategy":"try-catch","validationCode":"if ( stripos(PHP_OS, 'WIN') === 0 && $process->isRunning()) { /* proceed with kill */ }","typeGuard":null,"tryCatchPattern":"try { $process->stop(0, $sig); } catch (RuntimeException $e) { // taskkill failed\n    sleep(1); if ($process->isRunning()) { /* escalate/retry */ }\n}","preventionTips":["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"],"tags":["php","process","windows","taskkill","signal"],"backgroundTag":"command-not-found","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"}