fix: avoid systemd-supervised gateway retry loop in owned launcher (#700)
This commit is contained in:
committed by
GitHub
Unverified
parent
9b56d80d22
commit
514a6c4112
22
electron/gateway/config-sync-env.ts
Normal file
22
electron/gateway/config-sync-env.ts
Normal 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;
|
||||||
|
}
|
||||||
@@ -27,6 +27,8 @@ import { syncProxyConfigToOpenClaw } from '../utils/openclaw-proxy';
|
|||||||
import { logger } from '../utils/logger';
|
import { logger } from '../utils/logger';
|
||||||
import { prependPathEntry } from '../utils/env-path';
|
import { prependPathEntry } from '../utils/env-path';
|
||||||
import { copyPluginFromNodeModules, fixupPluginManifest, cpSyncSafe } from '../utils/plugin-install';
|
import { copyPluginFromNodeModules, fixupPluginManifest, cpSyncSafe } from '../utils/plugin-install';
|
||||||
|
import { stripSystemdSupervisorEnv } from './config-sync-env';
|
||||||
|
|
||||||
|
|
||||||
export interface GatewayLaunchContext {
|
export interface GatewayLaunchContext {
|
||||||
appSettings: Awaited<ReturnType<typeof getAllSettings>>;
|
appSettings: Awaited<ReturnType<typeof getAllSettings>>;
|
||||||
@@ -317,7 +319,7 @@ export async function prepareGatewayLaunchContext(port: number): Promise<Gateway
|
|||||||
? prependPathEntry(baseEnvRecord, binPath).env
|
? prependPathEntry(baseEnvRecord, binPath).env
|
||||||
: baseEnvRecord;
|
: baseEnvRecord;
|
||||||
const forkEnv: Record<string, string | undefined> = {
|
const forkEnv: Record<string, string | undefined> = {
|
||||||
...baseEnvPatched,
|
...stripSystemdSupervisorEnv(baseEnvPatched),
|
||||||
...providerEnv,
|
...providerEnv,
|
||||||
...uvEnv,
|
...uvEnv,
|
||||||
...proxyEnv,
|
...proxyEnv,
|
||||||
|
|||||||
45
tests/unit/config-sync.test.ts
Normal file
45
tests/unit/config-sync.test.ts
Normal 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' });
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user