History

fix(local): survive Windows libSQL handle linger during v1->v2 migration (#1209)

The v1->v2 data migration ran fsync/rename/remove on libSQL SQLite files whose native OS handle lingers past close() on Windows, crashing the daemon at boot with a fatal "Unknown error". POSIX never hits this, so it only reproduced on Windows (the v1.5.23 desktop/CLI startup regression). - fsyncFileIfExists opens read-write, since Windows FlushFileBuffers needs a writable handle (a read-only fd throws EPERM), and treats fsync as best-effort durability hardening. - remove of the source/staging file sets now retries EBUSY/EPERM the same way rename already did. - rename/remove retries force a GC pass first so libSQL's native finalizer releases the handle before the next attempt. Verified on a Windows VM: a seeded v1 database now migrates to v2 and the daemon announces ready.

Rhys Sullivan committed 4 months ago

Commit ffa4f701 parent b1d73bf2 files · +62 −14Browse files

Showing the changes to .changeset (1 of 2 files). Show all

Unified · Split

.changeset/windows-migration-handle-release.md+5−0
@@ -0,0 +1,5 @@
1+---
2+"executor": patch
3+---
4+
5+Fix the desktop and CLI daemon crashing on first launch on Windows when a v1 local database is present. The v1 to v2 data migration performed file operations (fsync, rename, remove) on libSQL SQLite files whose native OS handles linger after close() on Windows, surfacing as a fatal "Unknown error" (EPERM on fsync of a read-only handle, EBUSY on rename/remove of just-closed files). POSIX is unaffected, so this only reproduced on Windows. The migration now opens files read-write for fsync (treating it as best-effort), retries removes the same way renames were already retried, and forces a GC pass on each retry so libSQL's native finalizer releases the handle before the next attempt. Fixes the v1.5.23 Windows startup regression.