graphics: deletes and re-transmits leave image refcounts and placements out of step #79
Labels
No labels
Area/ci
Area/cli
Area/client
Area/client-core
Area/daemon
Area/deps
Area/docs
Area/grid
Area/manual
Area/nix
Area/protocol
Area/pty
Area/render
Area/shaping
Area/skills
Area/transport
Area/vt
Compat/Breaking
Kind/Bug
Kind/Documentation
Kind/Enhancement
Kind/Feature
Kind/Performance
Kind/Security
Kind/Testing
perf-regression-accepted
Reviewed
Confirmed
Reviewed
Duplicate
Reviewed
Invalid
Reviewed
Won't Fix
Status
Blocked
Status
Need More Info
Status
Upstream
No milestone
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
felis-terminal/felis#79
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The daemon's image refcounts and placement table drift from each other in three ways, all in
crates/felis-daemon/src/graphics.rs:delete_by_idwithp=(d=I,i=1,p=1) anddelete_filtered(d=A/C/P/Q/X/Y/Z/R) callfree_imagefor every touched image regardless of remaining placements.free_imageremoves the image and its virtual placements but not its regular placements, so the untouched placements stay in the daemon's table pointing at a deleted image. The client drops them onDelete, and a reattach re-sends them.kitty:
filter_refsfrees an image only once it has no refs left.i=keeps its placements.insert_into_storereplaces the entry, andImageStore::insertresets the refcount to 0 on the assumption that the dispatcher handles the old placements, but nothing does: they stay in both tables and now draw the new pixels, with a refcount of 0.kitty: "the existing image and all its placements must be deleted" (
free_refs_dataon re-transmit).(i, p)leaks a refcount.upsert_placementcallsimages.retainon everya=p, including one thatPlacements::upsertturns into a replacement, so an image placed N times under one placement id holds N refs after a single live placement. No visible effect has been found yet:evict_oldest_to_fitignores refcounts, so the only readers of a stale count are the animation tickers (advance_animations,next_animation_due_msincrates/felis-grid/src/images.rs).Repro (1):
a=T,i=1,p=1anda=p,i=1,p=2at another position, thena=d,d=I,i=1,p=1. kitty keeps placement 2 on screen and answers OK to a latera=p,i=1,p=3; felis removes the image and answers that place withENOENT.Repro (2): place
a=T,i=1,p=1, then re-transmita=t,i=1with different pixels and no placement. kitty clears the placement; felis redraws it with the new pixels.Confirmed (3) by reading only:
a=p,i=1,p=1twice, thena=d,d=i,i=1,p=1leaves the refcount at 1.Fix: make the refcount follow the placement table (release on replace, drop the placements on re-transmit with
PlacementRemovedevents), and free on an uppercase delete only images left with no placements.natsukium referenced this issue2026-10-09 23:23:27 +09:00