mirror of
https://github.com/moltbot/moltbot.git
synced 2026-03-07 22:44:16 +00:00
fix(supervisor): keep service-managed children attached (#38463, thanks @spirittechie)
Co-authored-by: Jesse Paul <drzin69@gmail.com>
This commit is contained in:
@@ -282,6 +282,7 @@ Docs: https://docs.openclaw.ai
|
||||
- Config/env substitution degraded mode: convert missing `${VAR}` resolution in config reads from hard-fail to warning-backed degraded behavior, while preventing unresolved placeholders from being accepted as gateway credentials. (#39050) Thanks @akz142857.
|
||||
- Discord inbound listener non-blocking dispatch: make `MESSAGE_CREATE` listener handoff asynchronous (no per-listener queue blocking), so long runs no longer stall unrelated incoming events. (#39154) Thanks @yaseenkadlemakki.
|
||||
- Daemon/Windows PATH freeze fix: stop persisting install-time `PATH` snapshots into Scheduled Task scripts so runtime tool lookup follows current host PATH updates; also refresh local TUI history on silent local finals. (#39139) Thanks @Narcooo.
|
||||
- Gateway/systemd service restart hardening: clear stale gateway listeners by explicit run-port before service bind, add restart stale-pid port-override support, tune systemd start/stop/exit handling, and disable detached child mode only in service-managed runtime so cgroup stop semantics clean up descendants reliably. (#38463) Thanks @spirittechie.
|
||||
|
||||
## 2026.3.2
|
||||
|
||||
|
||||
@@ -49,6 +49,8 @@ async function createAdapterHarness(params?: {
|
||||
}
|
||||
|
||||
describe("createChildAdapter", () => {
|
||||
const originalServiceMarker = process.env.OPENCLAW_SERVICE_MARKER;
|
||||
|
||||
beforeAll(async () => {
|
||||
({ createChildAdapter } = await import("./child.js"));
|
||||
});
|
||||
@@ -56,6 +58,11 @@ describe("createChildAdapter", () => {
|
||||
beforeEach(() => {
|
||||
spawnWithFallbackMock.mockClear();
|
||||
killProcessTreeMock.mockClear();
|
||||
if (originalServiceMarker === undefined) {
|
||||
delete process.env.OPENCLAW_SERVICE_MARKER;
|
||||
} else {
|
||||
process.env.OPENCLAW_SERVICE_MARKER = originalServiceMarker;
|
||||
}
|
||||
});
|
||||
|
||||
it("uses process-tree kill for default SIGKILL", async () => {
|
||||
@@ -90,6 +97,19 @@ describe("createChildAdapter", () => {
|
||||
expect(killMock).toHaveBeenCalledWith("SIGTERM");
|
||||
});
|
||||
|
||||
it("disables detached mode in service-managed runtime", async () => {
|
||||
process.env.OPENCLAW_SERVICE_MARKER = "openclaw";
|
||||
|
||||
await createAdapterHarness({ pid: 7777 });
|
||||
|
||||
const spawnArgs = spawnWithFallbackMock.mock.calls[0]?.[0] as {
|
||||
options?: { detached?: boolean };
|
||||
fallbacks?: Array<{ options?: { detached?: boolean } }>;
|
||||
};
|
||||
expect(spawnArgs.options?.detached).toBe(false);
|
||||
expect(spawnArgs.fallbacks ?? []).toEqual([]);
|
||||
});
|
||||
|
||||
it("keeps inherited env when no override env is provided", async () => {
|
||||
await createAdapterHarness({
|
||||
pid: 3333,
|
||||
|
||||
@@ -21,6 +21,10 @@ function resolveCommand(command: string): string {
|
||||
|
||||
export type ChildAdapter = SpawnProcessAdapter<NodeJS.Signals | null>;
|
||||
|
||||
function isServiceManagedRuntime(): boolean {
|
||||
return Boolean(process.env.OPENCLAW_SERVICE_MARKER?.trim());
|
||||
}
|
||||
|
||||
export async function createChildAdapter(params: {
|
||||
argv: string[];
|
||||
cwd?: string;
|
||||
@@ -34,11 +38,10 @@ export async function createChildAdapter(params: {
|
||||
|
||||
const stdinMode = params.stdinMode ?? (params.input !== undefined ? "pipe-closed" : "inherit");
|
||||
|
||||
// On Windows, `detached: true` creates a new process group and can prevent
|
||||
// stdout/stderr pipes from connecting when running under a Scheduled Task
|
||||
// (headless, no console). Default to `detached: false` on Windows; on
|
||||
// POSIX systems keep `detached: true` so the child survives parent exit.
|
||||
const useDetached = process.platform !== "win32";
|
||||
// In service-managed mode keep children attached so systemd/launchd can
|
||||
// stop the full process tree reliably. Outside service mode preserve the
|
||||
// existing POSIX detached behavior.
|
||||
const useDetached = process.platform !== "win32" && !isServiceManagedRuntime();
|
||||
|
||||
const options: SpawnOptions = {
|
||||
cwd: params.cwd,
|
||||
|
||||
Reference in New Issue
Block a user