mirror of https://github.com/openclaw/openclaw.git
fix(cron): prevent isolated cron nested lane deadlocks (#45459)
* fix(cron): resolve isolated session deadlock (#44805) Map cron lane to nested in resolveGlobalLane to prevent deadlock when isolated cron jobs trigger inner operations (e.g. compaction). Outer execution holds the cron lane slot; inner work now uses nested lane. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs(changelog): add cron isolated deadlock note --------- Co-authored-by: zhujian <zhujianxyz@gmail.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
3e6c8376fb
commit
28b0d8e8bd
|
|
@ -15,6 +15,7 @@ Docs: https://docs.openclaw.ai
|
|||
|
||||
- Browser/existing-session: accept text-only `list_pages` and `new_page` responses from Chrome DevTools MCP so live-session tab discovery and new-tab open flows keep working when the server omits structured page metadata.
|
||||
- Ollama/reasoning visibility: stop promoting native `thinking` and `reasoning` fields into final assistant text so local reasoning models no longer leak internal thoughts in normal replies. (#45330) Thanks @xi7ang.
|
||||
- Cron/isolated sessions: route nested cron-triggered embedded runner work onto the nested lane so isolated cron jobs no longer deadlock when compaction or other queued inner work runs. Thanks @vincentkoc.
|
||||
- Windows/gateway install: bound `schtasks` calls and fall back to the Startup-folder login item when task creation hangs, so native `openclaw gateway install` fails fast instead of wedging forever on broken Scheduled Task setups.
|
||||
- Windows/gateway auth: stop attaching device identity on local loopback shared-token and password gateway calls, so native Windows agent replies no longer log stale `device signature expired` fallback noise before succeeding.
|
||||
- Telegram/media downloads: thread the same direct or proxy transport policy into SSRF-guarded file fetches so inbound attachments keep working when Telegram falls back between env-proxy and direct networking. (#44639) Thanks @obviyus.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,44 @@
|
|||
import { describe, expect, it } from "vitest";
|
||||
import { CommandLane } from "../../process/lanes.js";
|
||||
import { resolveGlobalLane, resolveSessionLane } from "./lanes.js";
|
||||
|
||||
describe("resolveGlobalLane", () => {
|
||||
it("defaults to main lane when no lane is provided", () => {
|
||||
expect(resolveGlobalLane()).toBe(CommandLane.Main);
|
||||
expect(resolveGlobalLane("")).toBe(CommandLane.Main);
|
||||
expect(resolveGlobalLane(" ")).toBe(CommandLane.Main);
|
||||
});
|
||||
|
||||
it("maps cron lane to nested lane to prevent deadlocks", () => {
|
||||
// When cron jobs trigger nested agent runs, the outer execution holds
|
||||
// the cron lane slot. Inner work must use a separate lane to avoid
|
||||
// deadlock. See: https://github.com/openclaw/openclaw/issues/44805
|
||||
expect(resolveGlobalLane("cron")).toBe(CommandLane.Nested);
|
||||
expect(resolveGlobalLane(" cron ")).toBe(CommandLane.Nested);
|
||||
});
|
||||
|
||||
it("preserves other lanes as-is", () => {
|
||||
expect(resolveGlobalLane("main")).toBe(CommandLane.Main);
|
||||
expect(resolveGlobalLane("subagent")).toBe(CommandLane.Subagent);
|
||||
expect(resolveGlobalLane("nested")).toBe(CommandLane.Nested);
|
||||
expect(resolveGlobalLane("custom-lane")).toBe("custom-lane");
|
||||
expect(resolveGlobalLane(" custom ")).toBe("custom");
|
||||
});
|
||||
});
|
||||
|
||||
describe("resolveSessionLane", () => {
|
||||
it("defaults to main lane and prefixes with session:", () => {
|
||||
expect(resolveSessionLane("")).toBe("session:main");
|
||||
expect(resolveSessionLane(" ")).toBe("session:main");
|
||||
});
|
||||
|
||||
it("adds session: prefix if not present", () => {
|
||||
expect(resolveSessionLane("abc123")).toBe("session:abc123");
|
||||
expect(resolveSessionLane(" xyz ")).toBe("session:xyz");
|
||||
});
|
||||
|
||||
it("preserves existing session: prefix", () => {
|
||||
expect(resolveSessionLane("session:abc")).toBe("session:abc");
|
||||
expect(resolveSessionLane("session:main")).toBe("session:main");
|
||||
});
|
||||
});
|
||||
|
|
@ -7,6 +7,10 @@ export function resolveSessionLane(key: string) {
|
|||
|
||||
export function resolveGlobalLane(lane?: string) {
|
||||
const cleaned = lane?.trim();
|
||||
// Cron jobs hold the cron lane slot; inner operations must use nested to avoid deadlock.
|
||||
if (cleaned === CommandLane.Cron) {
|
||||
return CommandLane.Nested;
|
||||
}
|
||||
return cleaned ? cleaned : CommandLane.Main;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue