Sounds like you are experiencing a concurrency violation that doesn't necessarily result in crashing until things have been running long enough to finally hit the magic combination of events occurring at just the right time to bork things up.
You have three threads in your app: A GUI thread, a serial thread, and a camera thread. The serial and camera threads collect data from devices and then pass them on to the GUI thread for display. I presume the serial and camera threads don't share any data with each other, so there is no risk of problems there.
How are you passing data up from the serial and camera threads to the GUI thread? This is where you are probably having an issue.
Most complex data structures and Qt classes are not thread safe, meaning, they must never be read and written at the same time from two or more threads at the same time.
Here are some strategies for passing data between threads safely:
An integer is atomic at the CPU's instruction set level, so you can safely read and write an integer (or any data type equal to or smaller than an integer, such as a bool, a single char, or a pointer) from multiple threads without having any inconsistent state occurring. You must declare such variables with C++'s std::atomic<> template to ensure that the compiler will not perform optimizations that break atomicity.
Anything bigger/more complex than an integer runs the risk of one thread having written half of it's data to memory, while another thread concurrently reads out that half written data, resulting in very unexpected results, quite often crashing your application or getting something stuck in an infinite loop.
Signals and slots in Qt are thread safe. One way to pass complex data between threads is to emit
the data in one thread and have a slot
in another thread receive that data. Qt takes care of any concurrency issues under the hood for you in this case. The only gotcha here is if the consumer thread(s) of the data can not absorb the data fast enough, Qt's event queue will get stuffed up with too much data and eventually your app will crash because new GUI events (such as mouse clicks, repaint events, etc) can no longer get through the clogged up event queue.
You can use a QMutex
to ensure that only one thread is reading or writing a complex data structure at one time. QMutex
lets you block/halt execution in one or more threads while a single thread "holds" the mutex and allows it to execute, doing work on the data without any risk of other threads touching that data. When that one thread is done, it "releases" the mutex, which then allows one of the other threads to "hold" the mutex, resuming its execution so it can do work with the data.
As far as testing goes, typically the chances of your app crashing from a concurrency violation goes up the higher your data flow rates are. If you can artificially increase the rate of camera frames and "serial counts" being passed up to the GUI thread, you will be able to reproduce your application crash faster. Once you successfully solve your concurrency issues, you should be able to flood the system with data and never get it to crash.