diff --git a/src/main/services/TerminalSnapshotService.ts b/src/main/services/TerminalSnapshotService.ts index 7f67196c0..7937abd1b 100644 --- a/src/main/services/TerminalSnapshotService.ts +++ b/src/main/services/TerminalSnapshotService.ts @@ -62,6 +62,7 @@ async function readSnapshotFile(filePath: string): Promise { } } +async function atomicWriteFile(filePath: string, contents: string): Promise { + const dir = path.dirname(filePath); + const base = path.basename(filePath); + const tmpPath = path.join(dir, `.${base}.${process.pid}.${Date.now()}.tmp`); + await fs.promises.writeFile(tmpPath, contents, 'utf8'); + try { + await fs.promises.rename(tmpPath, filePath); + } catch (error) { + const code = (error as NodeJS.ErrnoException)?.code; + if (code === 'EEXIST' || code === 'EPERM') { + await fs.promises.rm(filePath, { force: true }); + await fs.promises.rename(tmpPath, filePath); + return; + } + await fs.promises.rm(tmpPath, { force: true }); + throw error; + } +} + async function listSnapshots(): Promise< Array<{ id: string; path: string; stats: StoredSnapshot }> > { @@ -121,7 +141,7 @@ class TerminalSnapshotService { } await ensureDir(); - await fs.promises.writeFile(snapshotPath(id), json, 'utf8'); + await atomicWriteFile(snapshotPath(id), json); await this.pruneIfNeeded(id); return { ok: true }; } catch (error) {