From 10113b2c9f6c84339a19b25fcfe2e11e7adbeff6 Mon Sep 17 00:00:00 2001 From: snowzlm <102895281+snowzlm@users.noreply.github.com> Date: Tue, 23 Jun 2026 02:54:21 +0800 Subject: [PATCH] fix(daemon): keep systemd gateway running after child OOM (#93585) Co-authored-by: snowzlm --- docs/gateway/index.md | 1 + docs/platforms/linux.md | 6 ++++++ src/daemon/systemd-unit.test.ts | 1 + src/daemon/systemd-unit.ts | 4 ++++ 4 files changed, 12 insertions(+) diff --git a/docs/gateway/index.md b/docs/gateway/index.md index 8d9f58e1c39..4034633c1d8 100644 --- a/docs/gateway/index.md +++ b/docs/gateway/index.md @@ -259,6 +259,7 @@ RestartSec=5 TimeoutStopSec=30 TimeoutStartSec=30 SuccessExitStatus=0 143 +OOMPolicy=continue KillMode=control-group [Install] diff --git a/docs/platforms/linux.md b/docs/platforms/linux.md index 114d86238ae..d2577b20eba 100644 --- a/docs/platforms/linux.md +++ b/docs/platforms/linux.md @@ -86,6 +86,7 @@ RestartSec=5 TimeoutStopSec=30 TimeoutStartSec=30 SuccessExitStatus=0 143 +OOMPolicy=continue KillMode=control-group [Install] @@ -130,6 +131,11 @@ cat /proc//oom_score_adj Expected value for covered children is `1000`. The Gateway process should keep its normal score, usually `0`. +The recommended systemd unit also sets `OOMPolicy=continue`. This keeps the +Gateway unit alive when a transient child process is selected by the OOM killer; +the child command/session can fail and report its error without systemd marking +the entire gateway service failed and restarting all channels. + This does not replace normal memory tuning. If a VPS or container repeatedly kills children, increase the memory limit, reduce concurrency, or add stronger resource controls such as systemd `MemoryMax=` or container-level memory limits. diff --git a/src/daemon/systemd-unit.test.ts b/src/daemon/systemd-unit.test.ts index a461f59db6c..7bdbd582216 100644 --- a/src/daemon/systemd-unit.test.ts +++ b/src/daemon/systemd-unit.test.ts @@ -23,6 +23,7 @@ describe("buildSystemdUnit", () => { expect(unit).toContain("TimeoutStopSec=30"); expect(unit).toContain("TimeoutStartSec=30"); expect(unit).toContain("SuccessExitStatus=0 143"); + expect(unit).toContain("OOMPolicy=continue"); expect(unit).toContain("StartLimitBurst=5"); expect(unit).toContain("StartLimitIntervalSec=60"); expect(unit).toContain("RestartPreventExitStatus=78"); diff --git a/src/daemon/systemd-unit.ts b/src/daemon/systemd-unit.ts index 8ac3d2e8f83..6802ba7aef6 100644 --- a/src/daemon/systemd-unit.ts +++ b/src/daemon/systemd-unit.ts @@ -81,6 +81,10 @@ export function buildSystemdUnit({ "TimeoutStopSec=30", "TimeoutStartSec=30", "SuccessExitStatus=0 143", + // Transient child processes may be selected by the OOM killer before the + // gateway. Keep the service running when that happens; the child surface is + // already responsible for reporting the failed command/session. + "OOMPolicy=continue", // Keep service children in the same lifecycle so restarts do not leave // orphan ACP/runtime workers behind. "KillMode=control-group",