Skip to content

Commit 842cb38

Browse files
committed
fix(studio-server): a history lock that cannot be read fails the open instead of spinning
1 parent ef040df commit 842cb38

3 files changed

Lines changed: 14 additions & 6 deletions

File tree

‎packages/studio-server/src/history/ownerLock.ts‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,9 @@ function ownerOf(file: string): number | null {
2424
try {
2525
const text = readFileSync(file, "utf-8");
2626
return /^\d+$/.test(text) ? Number(text) : Number.NaN;
27-
} catch {
28-
return null;
27+
} catch (error) {
28+
if ((error as NodeJS.ErrnoException).code === "ENOENT") return null;
29+
throw error;
2930
}
3031
}
3132

@@ -50,9 +51,8 @@ function releaseOwn(file: string): void {
5051
}
5152

5253
/**
53-
* Removes a dead owner's lock. One evictor at a time, re-reading the owner under its own lock, so a lock a live
54-
* process took after the caller's check survives. False when another evictor is at it. ponytail: an evictor that
55-
* dies mid-eviction leaves its lock to the next one that finds it dead, unguarded.
54+
* Removes a dead owner's lock under an evict lock, re-reading the owner, so a live owner's lock survives. False when
55+
* another evictor holds it. ponytail: a crashed evictor's lock is cleared unguarded; racing that can give two owners.
5656
*/
5757
function evictDeadOwner(file: string): boolean {
5858
const evictor = `${file}.evict`;

‎packages/studio-server/src/history/projectHistory.test.ts‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,15 @@ describe("openProjectHistory", () => {
234234
);
235235
});
236236

237+
it("fails an open whose lock cannot be read, instead of retrying it forever", async () => {
238+
const { history, projectDir, historyRoot } = await project({ "index.html": "v1" });
239+
await history.close();
240+
mkdirSync(join(historyRoot, history.projectId, "owner.pid"));
241+
await expect(openProjectHistory({ projectDir, historyRoot, ownerWaitMs: 0 })).rejects.toThrow(
242+
/EISDIR/,
243+
);
244+
});
245+
237246
it("takes over a lock file that holds no pid", async () => {
238247
const { history, projectDir, historyRoot } = await project({ "index.html": "v1" });
239248
await history.close();

‎packages/studio-server/src/history/projectHistory.ts‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ export interface ProjectHistoryOptions {
4242
ownerWaitMs?: number;
4343
}
4444

45-
/** Where HyperFrames keeps project histories: outside every project, so no tidy-up takes one away. */
4645
export const DEFAULT_HISTORY_ROOT = join(homedir(), ".cache", "hyperframes", "history");
4746

4847
export interface HistoryListItem extends HistoryEntry {

0 commit comments

Comments
 (0)