Skip to content

dax_rx stream lifecycle safety: borrowed streams not re-registered if creator removes them; audit TCI/DAX/RADE shared stream paths #1821

Description

@NF0T

Summary

The current dax_rx stream borrow pattern (used by TciServer and now activateRADE() on non-bridge platforms) has a lifecycle gap: if the stream creator removes the stream while a borrower still holds its ID, the borrower's audio silently dies with no error or re-registration.

Details

Both TciServer and the new RADE fix use the same pattern:

  1. Check panStream()->daxStreamIdForChannel(ch) — if non-zero, reuse (borrow) rather than create
  2. On release, skip stream remove for borrowed streams

The gap: if creator deactivates while borrower is active, the creator calls panStream()->unregisterDaxStream() and sends stream remove. The borrower still has the stream ID in its own tracking (m_tciDaxStreamIds[ch] or equivalent) but PanadapterStream no longer has it registered. Subsequent daxAudioReady signals for that channel stop firing because the VITA-49 routing is gone.

Concrete scenario: RADE activates (creates dax_rx stream) → TCI client connects (borrows it) → user deactivates RADE → stream removed → TCI audio dies silently.

The current workaround in the RADE fix skips stream remove if TCI has active clients, which prevents the problem in the most common case but is not a robust general solution.

Proposed Fix

Add reference counting to PanadapterStream for dax_rx stream registrations:

  • registerDaxStream(streamId, ch) increments a ref count per channel
  • unregisterDaxStream(streamId) decrements; only removes internal registration when count reaches zero
  • Callers that send stream remove should check the ref count first: only send when dropping to zero

This would allow any creator/borrower to release independently without needing to know about other consumers.

Scope of Audit

All places that create or remove dax_rx streams should be reviewed under this model:

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions