Repository navigation
Conversation
nazbert
added a commit
to nazbert/Deckard
that referenced
this pull request
Jul 12, 2026
…-load bg leak Three deck-lifecycle defects (issues StreamController#11, StreamController#12, StreamController#15): - StreamController#11: on a background-video page update_all_inputs skipped ALL key device writes (the per-frame loop paints keys) -- but the loop deliberately never repaints fully-opaque keys (their tile hides the video), so those never received their FIRST paint after a page switch: the device kept showing the previous page's content there until a keypress. The bg-video branch now update()s keys whose composed color is fully opaque; their tile hides the video, so the write cannot disturb it. - StreamController#12: close() step 6 ran plugin teardown hooks unbounded on the DeckClose thread. A wedged hook (pulsectl precedent) stranded steps 7-9 forever -- media sweep, fallback deck.close and deregistration never ran (the unplug leak reintroduced) and _closing=True made a retry a permanent no-op. Step 6 now runs on a daemon thread with a bounded join (TEARDOWN_JOIN_TIMEOUT_S, class-level for the harness); on timeout the hook thread is abandoned with a loud error and teardown completes. - StreamController#15: close() neither bumped _page_load_generation nor cancelled _bg_future, so an in-flight load that passed the _closing gate could attach a fresh BackgroundVideo (cv2 capture + registry ref + builder thread) AFTER step 7's resource sweep -- leaked until process exit. close() now invalidates the generation under _page_gen_lock and cancels the pending background future first thing. tests/scenario_deck_lifecycle_trio.py red-checks all three (writer stopped and drained for determinism on the paint check; the wedge is a blocking _teardown_actions with the timeout tightened; gen invalidation is checked with a pre-close generation capture).
nazbert
added a commit
to nazbert/Deckard
that referenced
this pull request
Jul 12, 2026
…aque UI push (review round 1) Follow-up to the deck-lifecycle trio, addressing MR !42 review round 1. - StreamController#15 (residual): the gen-bump + _bg_future.cancel() in close() only cover a load_background that has NOT yet reached its _page_is_current(gen) gate. A load already PAST that gate -- parked inside the seconds-long prebuild -- would still attach a fresh BackgroundVideo (cv2 capture) onto self.background.video AFTER close()'s step-7 sweep, leaking until process exit (the exact unplug-mid-switch leak StreamController#15 targets, via a different schedule). Closed with belt-and-suspenders: apply_prebuilt now re-checks _closing (set at the top of close(), before the sweep) and, when closing, discards the orphaned payload's resources instead of attaching it; and the step-7 background sweep runs under _background_load_lock so it cannot interleave with an in-flight attach. The _closing re-check is the load-bearing guard; the lock guarantees the sweep observes and releases the final background object rather than racing a concurrent set_video. - StreamController#11 (nit): opaque keys called update() (which paints device AND app preview) and then hit the unconditional UI-only mirror -- a redundant second UI push per opaque key. update() + continue now handles both; non-opaque keys still get the UI-only mirror (their device paint comes from the video loop). - StreamController#12 (doc): documented that the abandoned-teardown-thread residual is inherent to abandon-on-timeout, and that the wedge parks in clear_action_objects (before _teardown_actions's resource cleanup), so the residual surface is narrow -- a note for any future reordering. Tests (scenario_deck_lifecycle_trio.py): - New check_close_load_race: parks a load past its gen-gate, runs close()'s sweep, releases the load, asserts NO BackgroundVideo attaches on the closed controller and the orphaned payload was close()d. Red-checked (without the fix the leak reproduces); stable across repeated runs. - Strengthened check_opaque_initial_paint: asserts the opaque key's device write carries the NEW page's opaque-color bytes (journal content hash), not just that a write happened, plus a differential so the assertion can't pass vacuously. Harness: 89/89 PASS.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
1.3.0-beta release