Skip to content

Commit a7876bf

Browse files
committed
fix(session-lock): skip self-held max-hold reclaim
1 parent 1df9279 commit a7876bf

2 files changed

Lines changed: 30 additions & 3 deletions

File tree

src/agents/session-write-lock.test.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,32 @@ describe("acquireSessionWriteLock", () => {
345345
expect(inspected.staleReasons).toEqual([]);
346346
});
347347

348+
it("does not reclaim an active in-process lock through max-hold acquisition", async () => {
349+
await withTempSessionLockFile(async ({ sessionFile, lockPath }) => {
350+
const lock = await acquireSessionWriteLock({ sessionFile, timeoutMs: 500, maxHoldMs: 1 });
351+
await fs.writeFile(
352+
lockPath,
353+
JSON.stringify({
354+
pid: process.pid,
355+
createdAt: new Date(Date.now() - 30_000).toISOString(),
356+
maxHoldMs: 1,
357+
}),
358+
"utf8",
359+
);
360+
361+
await expect(
362+
acquireSessionWriteLock({
363+
sessionFile,
364+
timeoutMs: 5,
365+
staleMs: 60_000,
366+
allowReentrant: false,
367+
}),
368+
).rejects.toThrow(/session file locked/);
369+
await expect(fs.access(lockPath)).resolves.toBeUndefined();
370+
await lock.release();
371+
});
372+
});
373+
348374
it("watchdog releases stale in-process locks", async () => {
349375
const root = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-lock-"));
350376
const stderrSpy = vi.spyOn(process.stderr, "write").mockImplementation(() => true);

src/agents/session-write-lock.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -757,20 +757,21 @@ export async function acquireSessionWriteLock(params: {
757757
heldByThisProcess,
758758
reclaimLockWithoutStarttime: true,
759759
readOwnerProcessArgs: readProcessArgsSync,
760-
respectMaxHold: true,
760+
respectMaxHold: !heldByThisProcess,
761761
});
762762
return await shouldReclaimContendedLockFile(lockPath, inspected, staleMs, nowMs);
763763
},
764764
shouldRemoveStaleLock: async ({ lockPath, normalizedTargetPath, payload }) => {
765765
const nowMs = Date.now();
766+
const heldByThisProcess = sessionLockHeldByThisProcess(normalizedTargetPath);
766767
const inspected = inspectLockPayloadForSession({
767768
payload: payload as LockFilePayload | null,
768769
staleMs,
769770
nowMs,
770-
heldByThisProcess: sessionLockHeldByThisProcess(normalizedTargetPath),
771+
heldByThisProcess,
771772
reclaimLockWithoutStarttime: true,
772773
readOwnerProcessArgs: readProcessArgsSync,
773-
respectMaxHold: true,
774+
respectMaxHold: !heldByThisProcess,
774775
});
775776
return await shouldReclaimContendedLockFile(lockPath, inspected, staleMs, nowMs);
776777
},

0 commit comments

Comments
 (0)