惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Google DeepMind News
Google DeepMind News
aimingoo的专栏
aimingoo的专栏
爱范儿
爱范儿
D
Docker
I
InfoQ
Microsoft Security Blog
Microsoft Security Blog
G
Google Developers Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Vercel News
Vercel News
H
Hackread – Cybersecurity News, Data Breaches, AI and More
T
Tailwind CSS Blog
D
DataBreaches.Net
月光博客
月光博客
N
Netflix TechBlog - Medium
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
V
Visual Studio Blog
MyScale Blog
MyScale Blog
B
Blog
阮一峰的网络日志
阮一峰的网络日志
L
LangChain Blog
Recent Announcements
Recent Announcements
Microsoft Azure Blog
Microsoft Azure Blog
WordPress大学
WordPress大学

Recent Commits to openclaw:main

test: merge chat side-result checks · openclaw/openclaw@ddd2c2a test: merge cron history checks · openclaw/openclaw@f7eb746 test: merge responsive navigation shell checks · openclaw/openclaw@c2e4b47 docs(changelog): add codex oauth fixes · openclaw/openclaw@628e6cd test: merge navigation routing cases · openclaw/openclaw@5d8cecb Tests: mock channel registry bundled fallback · openclaw/openclaw@2b08233 Secrets: avoid broad web search discovery for single plugin config · openclaw/openclaw@a464f59 test: merge config view browser checks · openclaw/openclaw@20cf511 fix(status): align oauth health with runtime · openclaw/openclaw@eed7116 feat: add macOS screen snapshots for monitor preview (#67954) thanks … · openclaw/openclaw@f377db1 fix: report shared auth scopes in hello-ok (#67810) thanks @BunsDev · openclaw/openclaw@0b6c39b Auto-reply: avoid eager bundled route fallback · openclaw/openclaw@3ea1bf4 Tests: narrow session binding contract setup · openclaw/openclaw@54e4e16 fix(macOS): enable undo/redo in webchat composer text input (#34962) · openclaw/openclaw@00951dc Tests: speed up channel setup promotion · openclaw/openclaw@82b529a Docs: refresh agent instructions · openclaw/openclaw@5775fe2 fix(auth): serialize OAuth refresh across agents to fix #26322 (#67876) · openclaw/openclaw@8e79080 test: allow ollama public surface boundary test · openclaw/openclaw@7d4f1a6 Docs: add test performance guardrails · openclaw/openclaw@89706d3 Tests: restore context-engine usage proof · openclaw/openclaw@e4c4f95 Tests: slim context engine runtime coverage · openclaw/openclaw@74c198f ci: retry failed custom checkouts · openclaw/openclaw@0ee5baf test: trim duplicate provider auth onboarding cases · openclaw/openclaw@1ffc02e matrix: fix sessions_spawn --thread subagent session spawning (#67643) · openclaw/openclaw@1ce2596 test: reduce auth choice fixture churn · openclaw/openclaw@857b9cd test: mock health status config boundaries · openclaw/openclaw@9d5ab4a test: mock onboard config io boundary · openclaw/openclaw@299694d test: mock legacy state plugin boundaries · openclaw/openclaw@2713089 test: mock channel install boundaries · openclaw/openclaw@b945248 test: mock doctor preview channel boundaries · openclaw/openclaw@b1a3ad4
fix(agents): reclaim untracked self-owned session locks (...
cdznho · 2026-05-02 · via Recent Commits to openclaw:main

@@ -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+351362

function inspectLockPayload(

352363

payload: LockFilePayload | null,

353364

staleMs: number,

@@ -429,16 +440,51 @@ async function shouldReclaimContendedLockFile(

429440

function shouldTreatAsOrphanSelfLock(params: {

430441

payload: LockFilePayload | null;

431442

normalizedSessionFile: string;

443+

reclaimLockWithoutStarttime: boolean;

432444

}): boolean {

433445

const pid = isValidLockNumber(params.payload?.pid) ? params.payload.pid : null;

434446

if (pid !== process.pid) {

435447

return false;

436448

}

437-

const hasValidStarttime = isValidLockNumber(params.payload?.starttime);

438-

if (hasValidStarttime) {

449+

if (HELD_LOCKS.has(params.normalizedSessionFile)) {

439450

return 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

}

443489444490

export async function cleanStaleLockFiles(params: {

@@ -476,7 +522,15 @@ export async function cleanStaleLockFiles(params: {

476522

for (const entry of lockEntries) {

477523

const lockPath = path.join(sessionsDir, entry.name);

478524

const 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+

});

480534

const lockInfo: SessionLockInspection = {

481535

lockPath,

482536

...inspected,

@@ -515,13 +569,7 @@ export async function acquireSessionWriteLock(params: {

515569

const sessionFile = path.resolve(params.sessionFile);

516570

const sessionDir = path.dirname(sessionFile);

517571

await 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);

525573

const lockPath = `${normalizedSessionFile}.lock`;

526574527575

const held = HELD_LOCKS.get(normalizedSessionFile);

@@ -587,21 +635,14 @@ export async function acquireSessionWriteLock(params: {

587635

}

588636

const payload = await readLockPayload(lockPath);

589637

const 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)) {

605646

await fs.rm(lockPath, { force: true });

606647

continue;

607648

}