@@ -3,7 +3,7 @@ import type fsSync from "node:fs";
33import fs from "node:fs/promises" ;
44import path from "node:path" ;
55import { MAX_TIMER_TIMEOUT_MS } from "@openclaw/normalization-core/number-coercion" ;
6- import { createFileLockManager } from "../infra/file-lock-manager.js" ;
6+ import { createFileLockManager , type FileLockManager } from "../infra/file-lock-manager.js" ;
77import { readGatewayProcessArgsSync as readProcessArgsSync } from "../infra/gateway-processes.js" ;
88import { getProcessStartTime , isPidAlive } from "../shared/pid-alive.js" ;
99import { SessionWriteLockTimeoutError } from "./session-write-lock-error.js" ;
@@ -77,8 +77,10 @@ type LockInspectionDetails = Pick<
7777 "pid" | "pidAlive" | "createdAt" | "ageMs" | "stale" | "staleReasons"
7878> ;
7979
80+ type SessionLockAcquire = FileLockManager [ "acquire" ] ;
8081const SESSION_LOCKS = createFileLockManager ( "openclaw.session-write-lock" ) ;
8182let resolveProcessStartTimeForLock = getProcessStartTime ;
83+ let acquireSessionLockForTest : SessionLockAcquire | null = null ;
8284
8385function isFileLockError ( error : unknown , code : string ) : boolean {
8486 return ( error as { code ?: unknown } | null ) ?. code === code ;
@@ -818,10 +820,24 @@ export async function acquireSessionWriteLock(params: {
818820 await fs . mkdir ( sessionDir , { recursive : true } ) ;
819821
820822 while ( true ) {
823+ const elapsedBeforeAcquireMs = Date . now ( ) - startedAt ;
824+ const acquireTimeoutMs =
825+ timeoutMs === Number . POSITIVE_INFINITY
826+ ? timeoutMs
827+ : Math . max ( 0 , timeoutMs - elapsedBeforeAcquireMs ) ;
828+ if ( acquireTimeoutMs <= 0 ) {
829+ await throwSessionWriteLockTimeout ( {
830+ timeoutMs,
831+ lockPath,
832+ } ) ;
833+ }
834+
821835 try {
822- const lock = await SESSION_LOCKS . acquire ( sessionFile , {
836+ const acquireSessionLock =
837+ acquireSessionLockForTest ?? SESSION_LOCKS . acquire . bind ( SESSION_LOCKS ) ;
838+ const lock = await acquireSessionLock ( sessionFile , {
823839 staleMs,
824- timeoutMs,
840+ timeoutMs : acquireTimeoutMs ,
825841 retry : { minTimeout : 50 , maxTimeout : 1000 , factor : 1 } ,
826842 staleRecovery : "remove-if-unchanged" ,
827843 allowReentrant,
@@ -915,6 +931,9 @@ export const testing = {
915931 setProcessStartTimeResolverForTest ( resolver : ( ( pid : number ) => number | null ) | null ) : void {
916932 resolveProcessStartTimeForLock = resolver ?? getProcessStartTime ;
917933 } ,
934+ setSessionLockAcquireForTest ( acquire : SessionLockAcquire | null ) : void {
935+ acquireSessionLockForTest = acquire ;
936+ } ,
918937} ;
919938
920939export async function drainSessionWriteLockStateForTest ( ) : Promise < void > {
@@ -928,5 +947,6 @@ export function resetSessionWriteLockStateForTest(): void {
928947 stopWatchdogTimer ( ) ;
929948 unregisterCleanupHandlers ( ) ;
930949 resolveProcessStartTimeForLock = getProcessStartTime ;
950+ acquireSessionLockForTest = null ;
931951}
932952export { testing as __testing } ;
0 commit comments