























@@ -3992,6 +3992,103 @@ describe("embedded attempt session lock lifecycle", () => {
39923992expect(acquireSessionWriteLockLocal).toHaveBeenCalledTimes(2);
39933993});
399439943995+it("releaseHeldLockWithFence sets deferred flag when bailed out during active scope; re-attempted after scope deactivation (#95915)", async () => {
3996+const events: string[] = [];
3997+const releasePrep = vi.fn(async () => events.push("prep-release"));
3998+const releaseRetained = vi.fn(async () => events.push("retained-release"));
3999+const acquireSessionWriteLockLocal = vi
4000+.fn()
4001+.mockResolvedValueOnce({ release: releasePrep })
4002+.mockResolvedValueOnce({ release: releaseRetained });
4003+4004+const controller = await createEmbeddedAttemptSessionLockController({
4005+acquireSessionWriteLock: acquireSessionWriteLockLocal,
4006+ lockOptions,
4007+});
4008+4009+await controller.releaseForPrompt();
4010+await controller.reacquireAfterPrompt();
4011+4012+await controller.withSessionWriteLock(async () => {
4013+events.push("write-start");
4014+await controller.releaseHeldLockForAbort();
4015+events.push("write-end");
4016+});
4017+4018+expect(events).toEqual(["prep-release", "write-start", "write-end", "retained-release"]);
4019+expect(acquireSessionWriteLockLocal).toHaveBeenCalledTimes(2);
4020+});
4021+4022+it("controls the held lock lifecycle across deferred abort release, reacquisition, and prompt release", async () => {
4023+const events: string[] = [];
4024+const acquireSessionWriteLockLocal = vi
4025+.fn()
4026+.mockResolvedValueOnce({ release: vi.fn(async () => events.push("init-release")) })
4027+.mockResolvedValueOnce({ release: vi.fn(async () => events.push("held-release")) })
4028+.mockResolvedValueOnce({ release: vi.fn(async () => events.push("reacquire-release")) });
4029+4030+const controller = await createEmbeddedAttemptSessionLockController({
4031+acquireSessionWriteLock: acquireSessionWriteLockLocal,
4032+ lockOptions,
4033+});
4034+4035+await controller.releaseForPrompt();
4036+await controller.reacquireAfterPrompt();
4037+4038+await controller.withSessionWriteLock(async () => {
4039+events.push("write");
4040+await controller.releaseHeldLockForAbort();
4041+});
4042+4043+expect(events).toEqual(["init-release", "write", "held-release"]);
4044+4045+await controller.reacquireAfterPrompt();
4046+await controller.releaseForPrompt();
4047+4048+expect(events).toEqual(["init-release", "write", "held-release", "reacquire-release"]);
4049+expect(acquireSessionWriteLockLocal).toHaveBeenCalledTimes(3);
4050+});
4051+4052+it("takeHeldLockAfterRetainedIdle does not self-deadlock when called from inside active write scope (#95915)", async () => {
4053+const events: string[] = [];
4054+const acquireSessionWriteLockLocal = vi
4055+.fn()
4056+.mockResolvedValueOnce({ release: vi.fn(async () => events.push("init-release")) })
4057+.mockResolvedValueOnce({ release: vi.fn(async () => events.push("held-release")) })
4058+.mockRejectedValueOnce(
4059+new SessionWriteLockTimeoutError({
4060+timeoutMs: lockOptions.timeoutMs,
4061+owner: "pid=test",
4062+lockPath: `${lockOptions.sessionFile}.lock`,
4063+}),
4064+);
4065+4066+const controller = await createEmbeddedAttemptSessionLockController({
4067+acquireSessionWriteLock: acquireSessionWriteLockLocal,
4068+ lockOptions,
4069+});
4070+4071+await controller.releaseForPrompt();
4072+await controller.reacquireAfterPrompt();
4073+4074+const takeoverError = await controller
4075+.withSessionWriteLock(async () => {
4076+events.push("write-start");
4077+const cleanupLock = await controller.acquireForCleanup();
4078+await cleanupLock.release();
4079+events.push("cleanup-inside-done");
4080+})
4081+.catch((error: unknown) => error);
4082+4083+expect(takeoverError).toBeInstanceOf(EmbeddedAttemptSessionTakeoverError);
4084+4085+const cleanupLock = await controller.acquireForCleanup();
4086+await cleanupLock.release();
4087+4088+expect(events).toEqual(["init-release", "write-start", "cleanup-inside-done", "held-release"]);
4089+expect(acquireSessionWriteLockLocal).toHaveBeenCalledTimes(3);
4090+});
4091+39954092it("returns a no-op cleanup lock after prompt lock reacquisition times out", async () => {
39964093const releases: string[] = [];
39974094const acquireSessionWriteLockResult = vi
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。