Skip to content

Bump version to 1.2.1-beta - #11

Merged
Core447 merged 5 commits into
mainfrom
dev
Mar 28, 2024
Merged

Core447 merged 5 commits into
mainfrom
dev

Conversation

@Core447

@Core447 Core447 commented Mar 28, 2024

Copy link
Copy Markdown
Member

Bump version to 1.2.1-beta

@Core447
Core447 merged commit 9c717df into main Mar 28, 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.
nazbert added a commit to nazbert/Deckard that referenced this pull request Aug 9, 2026
…(refs StreamController#88)

The closure disposition claimed skipped keys self-heal within one 33 ms
tick. That was false for opaque keys -- the per-frame video loop never
repaints a key whose composed background colour is fully opaque, so after
a switch onto a background-video page those keys kept the previous page's
imagery until a keypress (issue StreamController#11).

Re-verified against the current tree: the opaque case is no longer a heal
at all -- update_all_inputs paints those keys itself in the bg-video
branch (ba45d41) and re-pushes the in-app preview for the rest
(2366b00), so it moves to the landed list. The keys that are still
skipped are exactly the ones on_media_player_tick repaints, and their
bound is the video write budget (_video_write_hz, default 30 Hz) rather
than the loop tick -- and it lapses entirely while the opt-in quiescence
gate is engaged, where the settle window does the paint instead.

The original v2 design below the fold is left unmodified, as the doc's
own framing requires.
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