{"record":{"id":"f15c203fda82308f","repo":"mihomo-party-org/clash-party","slug":"core-pid-proc-pid-unknown-did-not-exit-aft","errorCode":null,"errorMessage":"Core PID ${proc.pid ?? 'unknown'} did not exit after SIGINT; sending SIGKILL","messagePattern":"Core PID (.+?) did not exit after SIGINT; sending SIGKILL","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/main/core/manager.ts","lineNumber":872,"sourceCode":"    cleanupStoppedCoreResources()\n  ])\n}\n\nsetStopCoreBeforeAdminRestart(stopCore)\n\nasync function ensureCoreProcessExited(proc: ChildProcess | null): Promise<void> {\n  if (!proc) return\n\n  const waitForExit = async (): Promise<boolean> => {\n    const deadline = Date.now() + coreShutdownTimeout\n    while (proc.exitCode === null && proc.signalCode === null && Date.now() < deadline) {\n      await delay(50)\n    }\n    return proc.exitCode !== null || proc.signalCode !== null\n  }\n\n  if (await waitForExit()) return\n  managerLogger.warn(`Core PID ${proc.pid ?? 'unknown'} did not exit after SIGINT; sending SIGKILL`)\n  proc.kill('SIGKILL')\n  if (!(await waitForExit())) {\n    throw new Error(`Core PID ${proc.pid ?? 'unknown'} is still running after SIGKILL`)\n  }\n}\n\nasync function restartCoreOnce(forceStop: boolean): Promise<void> {\n  const startAttempt = await runCoreOperation(async () => {\n    const previousChild = child\n    await stopCoreInternal(forceStop)\n    if (process.platform === 'darwin') await ensureCoreProcessExited(previousChild)\n    return startCoreInternal(false, true)\n  })\n  await startAttempt.readiness\n}\n\nfunction trackCoreRestart(operation: () => Promise<void>): Promise<void> {\n  if (pendingRestart) return pendingRestart","sourceCodeStart":854,"sourceCodeEnd":890,"githubUrl":"https://github.com/mihomo-party-org/clash-party/blob/911e090537acdf7c50bee1c3aebecc2ef119a8b5/src/main/core/manager.ts#L854-L890","documentation":"stopCore sends SIGINT to the core (mihomo) process and waits for it to exit. If the process is still alive after the grace period, this warning is logged and SIGKILL is sent as a forced last resort; if even SIGKILL fails to terminate it, a hard error is thrown. The warning itself means the core ignored or was slow to handle the graceful shutdown signal.","triggerScenarios":"Core is hung (deadlocked, blocked on I/O) and not processing SIGINT; the process is in uninterruptible sleep (D state, e.g. stuck disk/network syscall); the binary ignores SIGINT; extremely slow shutdown exceeding the wait window under heavy load.","commonSituations":"Core wedged after network interface changes or TUN device issues; low-resource systems where shutdown is slow; core version bugs that mishandle signals; zombie/stuck states after long uptime.","solutions":["Usually self-healing — the SIGKILL path terminates the core; just restart the core/app.","If it recurs, update the core (mihomo) to the latest version where signal handling bugs may be fixed.","Check system state (dmesg/proc status) for processes stuck in uninterruptible I/O and resolve underlying I/O problems.","If 'still running after SIGKILL' errors appear, investigate OS-level issues (zombie children, PID namespace/container quirks) and reboot if needed."],"exampleFix":"// before\nmanagerLogger.warn(`Core PID ${proc.pid ?? 'unknown'} did not exit after SIGINT; sending SIGKILL`)\nproc.kill('SIGKILL')\n// after\nmanagerLogger.warn(`Core PID ${proc.pid ?? 'unknown'} did not exit after SIGINT; sending SIGKILL`)\nproc.kill('SIGKILL')\nawait trackShutdownFailure(proc) // report recurring SIGKILL reliance to telemetry for core bug triage","handlingStrategy":"try-catch","validationCode":"// Before stopping, check the process is still alive and killable:\nif (proc.exitCode !== null || proc.signalCode !== null) return // already exited\nif (proc.killed) console.warn('Core already signaled; forcing SIGKILL likely')","typeGuard":null,"tryCatchPattern":"try {\n  await stopCore(proc)\n} catch (e) {\n  if (e instanceof Error && e.message.includes('still running after SIGKILL')) {\n    // OS-level issue: investigate uninterruptible process, log PID for triage\n    managerLogger.error(`Core PID ${proc.pid} unkillable — check dmesg / D-state / container PID namespace`, e)\n  } else throw e\n}","preventionTips":["Keep the core (mihomo) updated to a version with reliable signal handling.","Avoid killing from external tools mid-shutdown; use the app's stop path.","Monitor for repeated SIGKILL reliance in logs — it signals a hung core worth investigating.","Check system I/O health; processes stuck in uninterruptible sleep cannot handle SIGINT."],"tags":["process","signal","shutdown"],"backgroundTag":"sigkill-after-graceful-shutdown-timeout","analyzedSha":"911e090537acdf7c50bee1c3aebecc2ef119a8b5","analyzedAt":"2026-08-30T13:00:49.174Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}