Skip to content

fix(scene-source): stop stranding stale browser_source on re-point (#110)#111

Merged
ClodoCapeo merged 2 commits into
mainfrom
forge/pulsar-110-scene-source-name-drift
Jul 5, 2026
Merged

fix(scene-source): stop stranding stale browser_source on re-point (#110)#111
ClodoCapeo merged 2 commits into
mainfrom
forge/pulsar-110-scene-source-name-drift

Conversation

@ClodoCapeo

Copy link
Copy Markdown
Contributor

Closes #110

Problem

on_set_capture_source created the new browser_source under the canonical name PulsarSceneSource before removing the old one. While the old source still held that name, libobs de-duped the fresh instance to PulsarSceneSource 2; remove_managed_items matched by exact strcmp and thus missed every numbered variant, which accreted on the program scene indefinitely. From the 3rd re-point on, a name-based consumer (Prism's findBrowserSourceName, first browser_source item) could lock onto a stale instance — the real-world symptom: REC on an atlas scene showing only the native camera, never the Solar overlay.

Fix

plugins/pulsar-scene-source/src/plugin-main.cpp:

  • Remove managed items before adding the fresh source; the scene held the old source's only ref, so removing the item frees the canonical name synchronously.
  • Reclaim the canonical name on the fresh source once it is free (obs_source_set_name) — the surviving instance is always PulsarSceneSource, never a numbered variant. No-op on the first call.
  • remove_managed_items now matches libobs de-dup variants (base or base <digits>, precisely — not a loose prefix), sweeping any pre-existing drift without over-matching an unrelated PulsarSceneSourceCustom.
  • The create-first order is kept for the availability check, so a light build (no obs-browser) still returns browser_source_unavailable without touching the scene.

Test

scripts/probe-scene-name-drift.py (connect-only, wired into the offline probe suite / CTest via run-probes.ps1): drives pulsar-scene:SetCaptureSource N=6 times against the shared pulsar.exe and asserts, after every call, that the program scene holds exactly one managed browser_source and that it carries the canonical name. This is the websocket-boundary equivalent of the investigation's probe_name_drift.py (pure libobs state, no CEF paint / GPU). Light build → typed exit-3 skip, same pattern as probe-browser-m3.py.

Not validated here

Real CEF pixel compositing after re-point (needs an interactive desktop + Solar) is out of CI scope by doctrine — the antenna/live path covers it.

🤖 Generated with Claude Code

on_set_capture_source created the new browser_source under the canonical
name PulsarSceneSource before removing the old one. While the old source
still owned that name, libobs de-duped the fresh instance to
"PulsarSceneSource 2"; remove_managed_items matched by exact strcmp and so
missed every numbered variant, which accreted on the program scene forever.
A name-based consumer (Prism's findBrowserSourceName) could then lock onto a
stale instance from the 3rd re-point on — the atlas-scene REC symptom.

Remove managed items before adding the fresh source, reclaim the canonical
name once it is free, and match managed items by libobs de-dup variant
("base <n>") so any pre-existing drift is swept too. Guarded by
scripts/probe-scene-name-drift.py in the offline probe suite (asserts exactly
one canonically-named browser_source across N SetCaptureSource calls).

Closes #110

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@ClodoCapeo ClodoCapeo force-pushed the forge/pulsar-110-scene-source-name-drift branch from 84d9df2 to 54bd9e3 Compare July 5, 2026 14:28
…ically

The previous fix reclaimed the canonical name by removing the old scene item
then set_name — assuming removal frees the name synchronously. CI proved that
false: obs_sceneitem_remove only schedules deferred source destruction, so the
old source could still own "PulsarSceneSource" at set_name time, leaving the
fresh source stuck as "PulsarSceneSource 2" (intermittent, one CI run failed,
a retry passed — a real race, not a flake).

remove_managed_items now renames each outgoing managed source to a unique
throwaway name before dropping its item. obs_source_set_name updates libobs's
global name table synchronously, so the canonical name is guaranteed free the
instant it returns — independent of when destruction actually runs. The
reclaim then verifies the name was applied (reads it back, warns on drift)
instead of assuming success. Probe hardened to 24 rapid re-points.

Closes #110

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@ClodoCapeo ClodoCapeo merged commit 2e15df4 into main Jul 5, 2026
14 checks passed
@ClodoCapeo ClodoCapeo deleted the forge/pulsar-110-scene-source-name-drift branch July 5, 2026 15:02
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.

on_set_capture_source : ancienne browser_source jamais nettoyée (nom renommé, strcmp exact la rate)

1 participant