fix(dab): stop ETI reader and release refcount on shared-mode teardown

Two fixes from code review:

1. Stop _eti_reader in Dablin.stop() (shared mode) — previously the cursor
   remained registered on SharedDabDecoder._eti_buffer after disconnect,
   forcing the buffer to retain data from the disconnected client's position
   until GC. With rapid connect/disconnect cycles this caused transient buffer
   bloat.

2. Release shared decoder refcount in _getDemodulator fallback path — if
   acquire() succeeded but Dablin.__init__ subsequently raised, _dabKey was
   cleared without calling release(), leaking one refcount and preventing the
   shared decoder from ever stopping.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Denny Ma 2026-03-15 18:32:07 +11:00
parent 7fb31b8648
commit 05bbe37322
2 changed files with 6 additions and 1 deletions

View file

@ -155,6 +155,9 @@ class Dablin(BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateChain,
self.processor.stop()
else:
self._meta_forwarder.stop()
if self._eti_reader is not None:
self._eti_reader.stop()
self._eti_reader = None
def setMetaWriter(self, writer: Writer) -> None:
if self._shared_decoder is None:

View file

@ -596,7 +596,9 @@ class DspManager(SdrSourceEventClient, ClientDemodulatorSecondaryDspEventClient)
return Dablin(shared_decoder=shared)
except Exception:
logger.exception("Shared DAB decoder failed, falling back to standalone")
self._dabKey = None
if self._dabKey is not None:
DabDecoderManager.getShared().release(*self._dabKey)
self._dabKey = None
return Dablin()
elif demod == "empty":
from csdr.chain.analog import Empty