MainWindow: Add FSMs to avoid blocking on GUI Thread#2274
MainWindow: Add FSMs to avoid blocking on GUI Thread#2274f4exb merged 7 commits intof4exb:masterfrom
Conversation
DSPDevice*Engine: Add signals to indicate when commands have been processed. DSPDeviceSourceEngine: Fix small memory leak. DSPEngine::removeDeviceEngineAt: Remove wait to avoid blocking thread. Return QThread to get finished signal. DSPEngine::addDevice*Engine: Don't call deleteLater for device*Engine, as these objects are deleted manually in MainWindow, which will crash if deleteLater called first.
…ndow::RemoveDeviceSetFSM::removeUI will do it
|
I am just wondering why the objects are deleted manually in MainWindow. |
I think previously it wasn't a problem, as the device removal all happen in one go. Now the FSMs return control part way through the removal it gives the deleteLater a chance to be called and then occasionally it would crash on the delete in MainWindow. This seemed to depend on whether I just closed the device or was exiting the program. Obviously feel free to change it however you want. |
|
It seems I cannot close the TestSink device using the cross (X) icon. This is what I see in the log: The generation stops but the GUI is still there. EDit: this is not systematic. In this case it happens in the second workspace (W1). |
|
Ok, I'll take a look Note that in DeviceGUi I changed the code to ignore the close event, as otherwise we would get a double delete (as MainWindow tries to delete it as well) |
|
It is a bit strange when I tried to reproduce the issue on a new instance of SDRangel the TestSink closed as it should. |
This is because all the subclasses of DeviceGUI call setAttribute(Qt::WA_DeleteOnClose, true);
I just tried on Windows a few times and it worked OK. |
My log shows: So after stopGeneration, I'd expect to see DSPDeviceSinkEngine::handleInputMessages to handle DSPGenerationStop. If that message isn't handled, it will not generate the generationStopped signal, and thus the RemoveDeviceSetFSM will not progress - as it waits for it, before going on to the next state. So I guess the question is why might DSPDeviceSinkEngine not be handling messages? |
|
The problem only happens when there is a modulator e.g the SSB modulator. Firstly when I stop the TestSink the SSB modultor stops but when I start again I cannot see the SSB modulator start debug message: Then if I stop again and try to close with (X) I get to the situation above: |
|
Ok, I can see the problem with the SSB and AM modulators, - but not the AIS or 802.15.4 modulators... |
|
This problem seems unrelated to this patch, as I think it also occurs in the release build of 7.22.1. Both SSB and AM Mod had threading changes in 7.22.1, so possibly something there. |
|
It looks like m_thread->wait(); in SSBMod::stop never returns. |
|
also I forgot to mention that I was still on your branch at commit |
|
For AISMod, after we call: m_thread->isFinished() returns true and m_thread->wait() returns immediately. However, for SSBMod, this isn't the case. m_thread->isFinished() returns false and m_thread->wait() hangs. It may be something to do with SSBMod being an audio sink, which the AISMod isn't. If I remove: From SSBModBaseband::SSBModBaseband then the thread exits. |
|
The thread isn't exiting, because it is blocked in SSBModBaseband::processFifo m_channelizer->pull() - it doesn't seem to return from that call. If I check the Audio Input button in the SSBMod, I don't see anything in the spectrum, with the 7.22.1 release, as I do with 7.22.0. (Maybe related to #2273?) |
I don't think so... More probably due to this commit: 75d40c8 as you suggested before. It does not seem possible to handle the thread life cycle in the start / stop methods. It has to be tightly linked to SSBModBaseband. Edit: what I find strange is that on the demod side (SSBDemod or WDSPRx) it works with the thread handled in start / stop. |


This PR adds some FSMs to MainWindow in order wait for events, while not blocking on the GUI Thread as discussed in #2159
DSPDeviceEngine: Add signals to indicate when commands have been processed.
DSPDeviceSourceEngine: Fix small memory leak.
DSPEngine::removeDeviceEngineAt: Remove wait to avoid blocking thread. Return QThread to get QThread :finished signal.
DSPEngine::addDeviceEngine: Don't call deleteLater for device*Engine, as these objects are deleted manually in MainWindow, which will crash if deleteLater called first.
I don't quite understand some of the code in MainWindow::sampleSinkCreate and MainWindow::sampleMIMOCreate. In the original code, it does:
but then:
Why getRxSamplingDevice rather than getMIMOSamplingDevice for the second call? I've left that as is for now.