You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
materialize uses link()+EEXIST to stop two processes from clobbering each other's session files, but the append path has no cross-process coordination. When two dsh processes share a session root: process A appends zstd frames while process B's loadStored reads a half-written frame, produces a tornMarker, and commitRepair → truncate(path, tornStart) cuts the tail of a frame A is still writing — A's handle was opened before the truncate and keeps writing from the old offset → holes/interleaved frames → corrupt log.
Evidence
packages/session/session-persistence-jsonl/src/index.ts:651-701 (appendLines/repair), 436-444 (commitRepair), 543-556 (materializePosix link+EEXIST guard comment: "two processes materializing the same id concurrently cannot clobber each other"), 292-304 (readStableFile).
The single-process coordinator serializes per-id (coordinator.ts:1010-1033), but cross-process there is no such protection, while other code paths (link guard, assertStoredIdentity duplicate-id check) explicitly assume a shared root is a multi-process scenario.
Trigger
Two processes (or profiles) sharing one session root with concurrent activity on the same session id.
Suggested fix
Use O_APPEND single atomic write + file-level flock on the append path (aligned with materialize's cross-process guard), or verify the file revision hasn't changed since the read (reuse readStableFile's stat loop) before commitRepair truncates.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Summary
materializeuseslink()+EEXISTto stop two processes from clobbering each other's session files, but the append path has no cross-process coordination. When two dsh processes share a session root: process A appends zstd frames while process B'sloadStoredreads a half-written frame, produces atornMarker, andcommitRepair→truncate(path, tornStart)cuts the tail of a frame A is still writing — A's handle was opened before the truncate and keeps writing from the old offset → holes/interleaved frames → corrupt log.Evidence
packages/session/session-persistence-jsonl/src/index.ts:651-701(appendLines/repair),436-444(commitRepair),543-556(materializePosixlink+EEXIST guard comment: "two processes materializing the same id concurrently cannot clobber each other"),292-304(readStableFile).The single-process coordinator serializes per-id (
coordinator.ts:1010-1033), but cross-process there is no such protection, while other code paths (link guard,assertStoredIdentityduplicate-id check) explicitly assume a shared root is a multi-process scenario.Trigger
Two processes (or profiles) sharing one session root with concurrent activity on the same session id.
Suggested fix
Use O_APPEND single atomic write + file-level flock on the append path (aligned with materialize's cross-process guard), or verify the file revision hasn't changed since the read (reuse
readStableFile's stat loop) beforecommitRepairtruncates.Verified at master
47f9438.All reactions