





















@@ -348,6 +348,17 @@ async function readLockPayload(lockPath: string): Promise<LockFilePayload | null
348348}
349349}
350350351+async function resolveNormalizedSessionFile(sessionFile: string): Promise<string> {
352+const resolvedSessionFile = path.resolve(sessionFile);
353+const sessionDir = path.dirname(resolvedSessionFile);
354+try {
355+const normalizedDir = await fs.realpath(sessionDir);
356+return path.join(normalizedDir, path.basename(resolvedSessionFile));
357+} catch {
358+return resolvedSessionFile;
359+}
360+}
361+351362function inspectLockPayload(
352363payload: LockFilePayload | null,
353364staleMs: number,
@@ -429,16 +440,51 @@ async function shouldReclaimContendedLockFile(
429440function shouldTreatAsOrphanSelfLock(params: {
430441payload: LockFilePayload | null;
431442normalizedSessionFile: string;
443+reclaimLockWithoutStarttime: boolean;
432444}): boolean {
433445const pid = isValidLockNumber(params.payload?.pid) ? params.payload.pid : null;
434446if (pid !== process.pid) {
435447return false;
436448}
437-const hasValidStarttime = isValidLockNumber(params.payload?.starttime);
438-if (hasValidStarttime) {
449+if (HELD_LOCKS.has(params.normalizedSessionFile)) {
439450return false;
440451}
441-return !HELD_LOCKS.has(params.normalizedSessionFile);
452+453+const storedStarttime = isValidLockNumber(params.payload?.starttime)
454+ ? params.payload.starttime
455+ : null;
456+if (storedStarttime === null) {
457+return params.reclaimLockWithoutStarttime;
458+}
459+460+const currentStarttime = getProcessStartTime(process.pid);
461+return currentStarttime !== null && currentStarttime === storedStarttime;
462+}
463+464+function inspectLockPayloadForSession(params: {
465+payload: LockFilePayload | null;
466+staleMs: number;
467+nowMs: number;
468+normalizedSessionFile: string;
469+reclaimLockWithoutStarttime: boolean;
470+}): LockInspectionDetails {
471+const inspected = inspectLockPayload(params.payload, params.staleMs, params.nowMs);
472+if (
473+!shouldTreatAsOrphanSelfLock({
474+payload: params.payload,
475+normalizedSessionFile: params.normalizedSessionFile,
476+reclaimLockWithoutStarttime: params.reclaimLockWithoutStarttime,
477+})
478+) {
479+return inspected;
480+}
481+return {
482+ ...inspected,
483+stale: true,
484+staleReasons: inspected.staleReasons.includes("orphan-self-pid")
485+ ? inspected.staleReasons
486+ : [...inspected.staleReasons, "orphan-self-pid"],
487+};
442488}
443489444490export async function cleanStaleLockFiles(params: {
@@ -476,7 +522,15 @@ export async function cleanStaleLockFiles(params: {
476522for (const entry of lockEntries) {
477523const lockPath = path.join(sessionsDir, entry.name);
478524const payload = await readLockPayload(lockPath);
479-const inspected = inspectLockPayload(payload, staleMs, nowMs);
525+const sessionFile = lockPath.slice(0, -".lock".length);
526+const normalizedSessionFile = await resolveNormalizedSessionFile(sessionFile);
527+const inspected = inspectLockPayloadForSession({
528+ payload,
529+ staleMs,
530+ nowMs,
531+ normalizedSessionFile,
532+reclaimLockWithoutStarttime: false,
533+});
480534const lockInfo: SessionLockInspection = {
481535 lockPath,
482536 ...inspected,
@@ -515,13 +569,7 @@ export async function acquireSessionWriteLock(params: {
515569const sessionFile = path.resolve(params.sessionFile);
516570const sessionDir = path.dirname(sessionFile);
517571await fs.mkdir(sessionDir, { recursive: true });
518-let normalizedDir = sessionDir;
519-try {
520-normalizedDir = await fs.realpath(sessionDir);
521-} catch {
522-// Fall back to the resolved path if realpath fails (permissions, transient FS).
523-}
524-const normalizedSessionFile = path.join(normalizedDir, path.basename(sessionFile));
572+const normalizedSessionFile = await resolveNormalizedSessionFile(sessionFile);
525573const lockPath = `${normalizedSessionFile}.lock`;
526574527575const held = HELD_LOCKS.get(normalizedSessionFile);
@@ -587,21 +635,14 @@ export async function acquireSessionWriteLock(params: {
587635}
588636const payload = await readLockPayload(lockPath);
589637const nowMs = Date.now();
590-const inspected = inspectLockPayload(payload, staleMs, nowMs);
591-const orphanSelfLock = shouldTreatAsOrphanSelfLock({
638+const inspected = inspectLockPayloadForSession({
592639 payload,
640+ staleMs,
641+ nowMs,
593642 normalizedSessionFile,
643+reclaimLockWithoutStarttime: true,
594644});
595-const reclaimDetails = orphanSelfLock
596- ? {
597- ...inspected,
598-stale: true,
599-staleReasons: inspected.staleReasons.includes("orphan-self-pid")
600- ? inspected.staleReasons
601- : [...inspected.staleReasons, "orphan-self-pid"],
602-}
603- : inspected;
604-if (await shouldReclaimContendedLockFile(lockPath, reclaimDetails, staleMs, nowMs)) {
645+if (await shouldReclaimContendedLockFile(lockPath, inspected, staleMs, nowMs)) {
605646await fs.rm(lockPath, { force: true });
606647continue;
607648}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。