detached 1c51966

docs(daemon): correct snapshot worker lock, transient page and geometry comments

commit
1c519666fec1f9c5d562e9216abfa12ff7791ba6
author
brice · · 2026-10-08 09:01 UTC
committer
brice · · 2026-10-08 09:31 UTC
parent
525159d
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
3 files · +9 -5
M internal/usecase/daemon/client.go +1 -0
@@ -238,6 +238,7 @@ func (ac *attachedClient) geometrySnapshot() domain.Geometry {
238238 if ac.geometry.Valid() {
239239 return ac.geometry
240240 }
241+ // Pixels only describe a valid cell size; never hand them out without one.
241242 return domain.Geometry{Size: ac.geometry.Size}
242243 }
243244
@@ -238,6 +238,7 @@ func (ac *attachedClient) geometrySnapshot() domain.Geometry {
238 if ac.geometry.Valid() {238 if ac.geometry.Valid() {
239 return ac.geometry239 return ac.geometry
240 }240 }
241+ // Pixels only describe a valid cell size; never hand them out without one.
241 return domain.Geometry{Size: ac.geometry.Size}242 return domain.Geometry{Size: ac.geometry.Size}
242 }243 }
243 244
M internal/usecase/daemon/render_pipeline.go +2 -1
@@ -59,7 +59,8 @@ type composeCacheInput struct {
5959 // the same commit/spare rotation as the cached frame, so a page is only ever
6060 // written by a composition whose input scratch owns it. Neither slot may hold
6161 // a page shared with a cached frame (frame, copyViewport.frame) or with another
62-// slot; they are filled only by copyFrameInto, which allocates a fresh page.
62+// slot; they are filled only by copyFrameInto, whose first fill clones, so a
63+// slot never shares a page with a cached frame.
6364 type transientFrames struct {
6465 // overlay receives the toast-decorated or modal-decorated copy of the base
6566 // frame. Toasts and modals never both clone, so they share the slot.
@@ -59,7 +59,8 @@ type composeCacheInput struct {
59 // the same commit/spare rotation as the cached frame, so a page is only ever59 // the same commit/spare rotation as the cached frame, so a page is only ever
60 // written by a composition whose input scratch owns it. Neither slot may hold60 // written by a composition whose input scratch owns it. Neither slot may hold
61 // a page shared with a cached frame (frame, copyViewport.frame) or with another61 // a page shared with a cached frame (frame, copyViewport.frame) or with another
62-// slot; they are filled only by copyFrameInto, which allocates a fresh page.62+// slot; they are filled only by copyFrameInto, whose first fill clones, so a
63+// slot never shares a page with a cached frame.
63 type transientFrames struct {64 type transientFrames struct {
64 // overlay receives the toast-decorated or modal-decorated copy of the base65 // overlay receives the toast-decorated or modal-decorated copy of the base
65 // frame. Toasts and modals never both clone, so they share the slot.66 // frame. Toasts and modals never both clone, so they share the slot.
M internal/usecase/daemon/snapshot_worker_state.go +6 -4
@@ -9,10 +9,12 @@ import (
99 // other durable writers joined with it (maintenance and restoration), so
1010 // WaitDurableWriters can read all three completion signals under one lock.
1111 //
12-// Lock position: mu is a leaf with respect to Daemon.mu. No code path acquires
13-// Daemon.mu, a session lock, or a pane lock while holding it, and capture,
14-// queue, and worker code never takes Daemon.mu. noticeMu is likewise a leaf and
15-// is never held together with mu.
12+// Lock position: mu is a leaf with respect to Daemon.mu and the session (mu),
13+// tab, and pane locks: no path acquires any of them while holding it, and
14+// capture, queue, and worker code never takes Daemon.mu. The one nested lock is
15+// a session's snapshotMu, taken under mu by enqueueFinalSnapshotCapture; see
16+// the lock-ordering notes in client.go. noticeMu is a leaf and is never held
17+// together with mu.
1618 //
1719 // The zero value is usable for tests that build &Daemon{}: nil maps are
1820 // allocated lazily by the enqueue paths, and a nil jobs channel never becomes
@@ -9,10 +9,12 @@ import (
9 // other durable writers joined with it (maintenance and restoration), so9 // other durable writers joined with it (maintenance and restoration), so
10 // WaitDurableWriters can read all three completion signals under one lock.10 // WaitDurableWriters can read all three completion signals under one lock.
11 //11 //
12-// Lock position: mu is a leaf with respect to Daemon.mu. No code path acquires12+// Lock position: mu is a leaf with respect to Daemon.mu and the session (mu),
13-// Daemon.mu, a session lock, or a pane lock while holding it, and capture,13+// tab, and pane locks: no path acquires any of them while holding it, and
14-// queue, and worker code never takes Daemon.mu. noticeMu is likewise a leaf and14+// capture, queue, and worker code never takes Daemon.mu. The one nested lock is
15-// is never held together with mu.15+// a session's snapshotMu, taken under mu by enqueueFinalSnapshotCapture; see
16+// the lock-ordering notes in client.go. noticeMu is a leaf and is never held
17+// together with mu.
16 //18 //
17 // The zero value is usable for tests that build &Daemon{}: nil maps are19 // The zero value is usable for tests that build &Daemon{}: nil maps are
18 // allocated lazily by the enqueue paths, and a nil jobs channel never becomes20 // allocated lazily by the enqueue paths, and a nil jobs channel never becomes

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 12

Tags 11

↑↓ moveenter openesc close