fix: avoid systemd-supervised gateway retry loop in owned launcher (#700)

This commit is contained in:
Lingxuan Zuo
2026-03-28 15:34:01 +08:00
committed by GitHub
Unverified
parent 9b56d80d22
commit 514a6c4112
3 changed files with 70 additions and 1 deletions

View File

@@ -0,0 +1,22 @@
export const SUPERVISED_SYSTEMD_ENV_KEYS = [
'OPENCLAW_SYSTEMD_UNIT',
'INVOCATION_ID',
'SYSTEMD_EXEC_PID',
'JOURNAL_STREAM',
] as const;
export type GatewayEnv = Record<string, string | undefined>;
/**
* OpenClaw CLI treats certain environment variables as systemd supervisor hints.
* When present in ClawX-owned child-process launches, it can mistakenly enter
* a supervised process retry loop. Strip those variables so startup follows
* ClawX lifecycle.
*/
export function stripSystemdSupervisorEnv(env: GatewayEnv): GatewayEnv {
const next = { ...env };
for (const key of SUPERVISED_SYSTEMD_ENV_KEYS) {
delete next[key];
}
return next;
}

View File

@@ -27,6 +27,8 @@ import { syncProxyConfigToOpenClaw } from '../utils/openclaw-proxy';
import { logger } from '../utils/logger';
import { prependPathEntry } from '../utils/env-path';
import { copyPluginFromNodeModules, fixupPluginManifest, cpSyncSafe } from '../utils/plugin-install';
import { stripSystemdSupervisorEnv } from './config-sync-env';
export interface GatewayLaunchContext {
appSettings: Awaited<ReturnType<typeof getAllSettings>>;
@@ -317,7 +319,7 @@ export async function prepareGatewayLaunchContext(port: number): Promise<Gateway
? prependPathEntry(baseEnvRecord, binPath).env
: baseEnvRecord;
const forkEnv: Record<string, string | undefined> = {
...baseEnvPatched,
...stripSystemdSupervisorEnv(baseEnvPatched),
...providerEnv,
...uvEnv,
...proxyEnv,

View File

@@ -0,0 +1,45 @@
import { describe, expect, it } from 'vitest';
import { stripSystemdSupervisorEnv } from '@electron/gateway/config-sync-env';
describe('stripSystemdSupervisorEnv', () => {
it('removes systemd supervisor marker env vars', () => {
const env = {
PATH: '/usr/bin:/bin',
OPENCLAW_SYSTEMD_UNIT: 'openclaw-gateway.service',
INVOCATION_ID: 'abc123',
SYSTEMD_EXEC_PID: '777',
JOURNAL_STREAM: '8:12345',
OTHER: 'keep-me',
};
const result = stripSystemdSupervisorEnv(env);
expect(result).toEqual({
PATH: '/usr/bin:/bin',
OTHER: 'keep-me',
});
});
it('keeps unrelated variables unchanged', () => {
const env = {
NODE_ENV: 'production',
OPENCLAW_GATEWAY_TOKEN: 'token',
CLAWDBOT_SKIP_CHANNELS: '0',
};
expect(stripSystemdSupervisorEnv(env)).toEqual(env);
});
it('does not mutate source env object', () => {
const env = {
OPENCLAW_SYSTEMD_UNIT: 'openclaw-gateway.service',
VALUE: '1',
};
const before = { ...env };
const result = stripSystemdSupervisorEnv(env);
expect(env).toEqual(before);
expect(result).toEqual({ VALUE: '1' });
});
});