graphics: a session's placement table has no size bound #88

Closed
opened 2026-10-10 04:07:37 +09:00 by natsukium · 0 comments
Owner

A session's Kitty graphics placement table has no size bound. Each placement costs a table entry in the daemon and in every attached client's shadow, but nothing of the image store's 256 MiB byte budget, so a producer can grow both without limit by repeating puts of one small image: a=p,i=1 with a fresh p= each time, or, since id-less puts became placements of their own, simply a=p,i=1 without p=.

The upsert scan over the table is also linear, so a large table slows every put.

kitty does not cap refs either, but a felis session outlives its window and its clients mirror the table, so the cost lands on the daemon and every client.

Repro: transmit a 1×1 image, then send \e_Ga=p,i=1,c=1,r=1,q=2\e\\ in a loop; the daemon's and the client's memory grow without bound.

Decide: a per-session placement cap, set well above real producers (yazi's per-cell preview places a few thousand per image), evicting the oldest placement past it with its ref released and PlacementRemoved sent, or refusing the put with ENOSPC-style error. Also whether the table needs an index keyed by (image_id, placement_id) once it can be large.

A session's Kitty graphics placement table has no size bound. Each placement costs a table entry in the daemon and in every attached client's shadow, but nothing of the image store's 256 MiB byte budget, so a producer can grow both without limit by repeating puts of one small image: `a=p,i=1` with a fresh `p=` each time, or, since id-less puts became placements of their own, simply `a=p,i=1` without `p=`. The upsert scan over the table is also linear, so a large table slows every put. kitty does not cap refs either, but a felis session outlives its window and its clients mirror the table, so the cost lands on the daemon and every client. **Repro:** transmit a 1×1 image, then send `\e_Ga=p,i=1,c=1,r=1,q=2\e\\` in a loop; the daemon's and the client's memory grow without bound. **Decide:** a per-session placement cap, set well above real producers (yazi's per-cell preview places a few thousand per image), evicting the oldest placement past it with its ref released and `PlacementRemoved` sent, or refusing the put with `ENOSPC`-style error. Also whether the table needs an index keyed by `(image_id, placement_id)` once it can be large.
Sign in to join this conversation.
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
felis-terminal/felis#88
No description provided.