Fix crash and session saving.

This commit is contained in:
Greyson Parrelli committed 2026-09-24 12:43:41 -04:00
1 parent 2a0e03cc41
commit 0e8bc70151
9 files changed
+353 -25

No files matched your search

+15 -5
View File
@@ -23,7 +23,7 @@
//!
//! It lives in the *state* directory rather than beside `layouts.json` and
//! `settings.json` in the config one. Those two are files a person writes;
//! this one is written behind their back on every exit, and putting churn like
//! this one is written behind their back every few seconds and on every exit, and putting churn like
//! that in a config directory — which plenty of people keep in version control
//! — would make every quit look like an edit. `$XDG_STATE_HOME` is where the
//! spec puts exactly this: state that should carry across restarts but that
@@ -276,27 +276,37 @@ pub const SaveError = error{ OutOfMemory, WriteFailed };
/// nothing about that state worth offering to restore — so the offer should not
/// appear at the next launch, and the stale one it would otherwise still be
/// holding should not either.
pub fn save(self: *Snapshot) SaveError!void {
///
/// `written` is a hash of what the caller last had written, and is updated to
/// this one's. A snapshot that would write the same bytes again is skipped: the
/// window is photographed every few seconds while it is open, and nearly every
/// one of those photographs is the same as the last.
pub fn save(self: *Snapshot, written: *u64) SaveError!void {
var path_buf: [max_path]u8 = undefined;
const path = statePath(&path_buf) orelse return error.WriteFailed;
if (!self.any()) {
remove(path);
written.* = 0;
return;
}
const text = try self.serialize();
defer self.arena.child_allocator.free(text);
const hash = std.hash.Wyhash.hash(0, text);
if (hash == written.*) return;
var dir_buf: [max_path]u8 = undefined;
const dir = stateDir(&dir_buf) orelse return error.WriteFailed;
if (glib.mkdirWithParents(dir.ptr, 0o700) != 0) return error.WriteFailed;
const text = try self.serialize();
defer self.arena.child_allocator.free(text);
var err: ?*glib.Error = null;
if (glib.fileSetContents(path.ptr, text.ptr, @intCast(text.len), &err) == 0) {
if (err) |e| e.free();
return error.WriteFailed;
}
written.* = hash;
}
/// Delete the file. Failures are ignored on purpose: the common one is it not