Files
sdrangel/plugins/samplesink
norcal88andClaude Fable 5.1 0f8dbc2574 PlutoSDR: serialize sample thread lifecycle across buddies
stop() tore the sample thread down with stopWork() + delete and only then
cleared m_deviceShared.m_thread. The buddy's applySettings() suspends and
resumes that thread through m_thread from another thread, without holding
this device's mutex, so it could restart the thread between stopWork() and
delete (QThread: Destroyed while thread is still running -> qFatal/abort),
or call through the pointer after the delete. The device's own
applySettings() had the same exposure on its own thread pointer, since it
does not take m_mutex either.

Seen when the Satellite Tracker loads presets into the Rx and Tx device
sets of one Pluto at AOS: abort in PlutoSDRInputThread::~PlutoSDRInputThread
<- PlutoSDRInput::stop <- DSPDeviceSourceEngine::gotoIdle.

Add DevicePlutoSDRShared::m_threadsMutex (recursive, shared by all PlutoSDR
device sets) and take it in start() around startWork()/publish, in stop()
and handleError() around unpublish + teardown (unpublishing first), in
suspendBuddies()/resumeBuddies(), and for the whole suspend -> apply ->
resume sequence in applySettings(). Also wait() before deleting the thread
and check the own-thread pointer before resuming it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-02 21:28:38 -07:00
..