Is there something else I should be doing? Like stopping the thread temporarily when loading a new file? I've come across a couple of posts from others with the same issue, but it makes no sense to me why this would happen.

@SGaist Yes I am. I've been told this is not the correct way to use QThreads but other say its just a matter of choice. Should I try passing a QObject to a thread instead?

Its worth mentioning that the problem is narrowed down to the .read() method of VideoCapture. Loading doesn't cause a crash. I tried using a lock and mutex right before reading a frame which seems to avoid a crash but the .read() method still hangs. Using mutex alone (locked before read, unlocked after) causes a crash as before.

@JKSH I override the run function of the subclassed QThread object. I only call VideoCapture methods from a single QThread. These aren't thread-safe from what I've read online but even so I shouldn't have an issue if accessing them from one thread only unless there's something going on in the background that I don't know.

The issue is that if I move the VideoCaptures to the main thread, the issue is fixed but I get crashes when they are part of the QThread.

Important note: Just because you call something from within a QThread method, that does not mean the code runs in the related thread!

Earlier, you said

The buttons end up calling this function in the QThread:

Well, Test::load() is running in the main thread, not your other thread.

If you want to verify this yourself, add qDebug() << QThread::currentThread() into the top of main(), the top of your run() function, and the top of Test::load(). This will show you which thread is running each function.

Read the QThread documentation carefully: https://doc.qt.io/qt-5/qthread.html. It says, "...a developer who wishes to invoke slots in the new thread must use the worker-object approach; new slots should not be implemented directly into a subclassed QThread.

When you reimplemented QThread::run(), you used an infinite loop (while (true)). This means your thread does not have an event loop, which means you cannot "trigger" anything in that thread.

@JKSH Thanks for the explanation. When a GUI button is pressed the thread is QThread(0x1922e9b0) and when the Test::load() is called, the thread is Test(0x197ded38) which is a bit confusing in terms of the names but looks like they are separate. I'm going to switch to what the documentation outlines and get back with the results.
On this note, how do I re-implement the event loop or make the thread continuously run without overriding the run() functions?

@JKSH I went back and noticed I had the qDebug() statement in the wrong place. You were correct about which thread a called method runs in. If the main thread calls a method in another thread, that method still runs in the main thread as the documentation says.

The issue was related to thread-safety as you suggested. Its also important to make sure we are not reading from a VideoCapture device that is in the process of loading a new video.

Here are my 'read' / 'load' methods for anyone having issues with this:

I'm still a bit confused about where exec() would come in, the documentation is a little hazy to me. Any SAFE threads you guys could reference that clears up how I need to implement run() and exec() together?

I'm still a bit confused about where exec() would come in, the documentation is a little hazy to me. Any SAFE threads you guys could reference that clears up how I need to implement run() and exec() together?

@JKSH Thanks a lot for taking the time to explain. The concept makes sense. After this->exec() is run with the event loop approach, the thread object is listed for deletion and its run() method cannot be called again. Is that correct? If so, then the thread object has to be created every time?

After this->exec() is run with the event loop approach, the thread object is listed for deletion and its run() method cannot be called again. Is that correct? If so, then the thread object has to be created every time?

Nope, exec() does not mark anything for deletion.

You can certainly start() and quit() a thread with an event loop multiple times. (Note: Quit does nothing if your thread has no event loop)

I'm still seeing this same crash happen when I load new videos into an OpenCV VideoCapture object. It is a lot less frequent, it happens when I test the GUI loading files quickly one after the other.

But what is a bit confusing is that I don't get any details about what goes wrong exactly (reading a few posts with this message I understand this is related to an invalid pointer being accessed somewhere). I've tried puting try / catch statements various places in my code to get something.

What I get from QT test when running the same test automatically and the crash happens is something like this:

@JKSH Thank for the reply! Aaah so 'Nearby Symbol' is where it occured and 'Exception Code' is what the error was. For future debugging is there a way I could get the stack trace when running the project normally? Currently the only way I could get it was by using QT unit test to start the GUI application.

I will try upgrading to QT 5.13. Any idea what could be inviting QColorProfile::fromSRgb() to the party?

I get this warning a few times everytime I start the project:

libpng warning: iCCP: known incorrect sRGB profile

I looked around online and people said it wasn't really a big deal but it seems it is related to the method that caused the crash.

Normally, the function where the crash occured will be item #1 on the stack trace because it's the last one called. However, since you're running inside a test framework, it was able to "catch" the crash and do some more work to present the crash to you (starting from UserExceptionDispatcher())

Any idea what could be inviting QColorProfile::fromSRgb() to the party?

Judging by your stack trace, your system is in the middle of decoding or rendering the video when the crash occurs.

For future debugging is there a way I could get the stack trace when running the project normally? Currently the only way I could get it was by using QT unit test to start the GUI application.

@JKSH Thanks for the detailed information, it'll definitely help with future bugs like this.

So far, it seems to crash more frequently when I load files quickly but I also tried slowing down the test and it still happened with no real pattern.

I have QMutexlockers in key areas where I load and read videos but after doing some more testing, it seems the crash happens only when I emit a signal containing an OpenCV matrix data pointer. I use this signal to display image results using a subclassed widget. If I don't emit the signal and use an OpenCV window to show an image, everything runs well no matter how fast I load videos. So I think there's something wrong in my handling of the sent pointer.

I don't see what in here could be causing a crash specially given that I use a const pointer. Is there a way I could catch the exception when it happens if I can't get to the bottom of the issue? So far try / catch statements haven't helped.

The constructor you are using does not make a copy of the data and you have to ensure that the lifetime of the buffer pointed to by imageData stays valid as long as the displayImage is.

From the looks of it, you should either call copy so that displayImage doesn't depend on the lifetime of imageData or create imageData once with the right dimensions and use memcpy to transfer the data. Re-create displayImage if the size changes at some point.

I think this fixed the issue. I got a couple of crashes in 'memcpy' but that was when loading files a little too quickly. I think most likey resizing the data quickly was the issue. I will do more testing this week and post the results.

UPDATE: I did a lot more testing and making a local copy fixed the issue. The issue was that I was modifying the array before it was fully copied and this caused crashes when the array was downsized. I will need to revise the overall structure to make sure everything is done sequentially.