Skip to content

1.3.1-beta release - #15

Merged
Core447 merged 8 commits into
mainfrom
dev
Mar 30, 2024
Merged

Core447 merged 8 commits into
mainfrom
dev

Conversation

@Core447

@Core447 Core447 commented Mar 30, 2024

Copy link
Copy Markdown
Member

1.3.1-beta release

@Core447
Core447 merged commit 4049aad into main Mar 30, 2024
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant