OpenCV VideoCapture Failure from QThread
-
@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?
-
You're welcome.
@rtavakko said in OpenCV VideoCapture Failure from QThread:
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()
andquit()
a thread with an event loop multiple times. (Note: Quit does nothing if your thread has no event loop) -
Hey guys,
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:
A crash occurred in C:\Users\Roham\Desktop\Lyrha\Modules\build-MorphTest-Desktop_Qt_5_12_0_MinGW_64_bit-Release\release\tst_morphtesttest.exe. Function time: 33587ms Total time: 34304ms Exception address: 0x0000000061b8afac Exception code : 0xc0000005 Nearby symbol : ZN13QColorProfile8fromSRgbEv Stack: # 1: ZN5QTest15toPrettyUnicodeEPKti() - 0x000000006edc2750 # 2: UnhandledExceptionFilter() - 0x00007fff41b0f490 # 3: memset() - 0x00007fff447a2fc0 # 4: _C_specific_handler() - 0x00007fff4478c640 # 5: _chkstk() - 0x00007fff447a10e0 # 6: RtlRaiseException() - 0x00007fff44769ef0 # 7: KiUserExceptionDispatcher() - 0x00007fff4479fe40 # 8: ZN13QColorProfile8fromSRgbEv() - 0x0000000061b1e470 # 9: ZN13QVulkanWindow11qt_metacallEN11QMetaObject4CallEiPPv() - 0x0000000061d1c190 # 10: ZN13QColorProfile8fromSRgbEv() - 0x0000000061b1e470 # 11: ZrsR11QDataStreamR8QPolygon() - 0x0000000061c29620 # 12: ZN18QRasterPaintEngine4clipERK11QVectorPathN2Qt13ClipOperationE() - 0x0000000061bd93d0 # 13: ZN8QPainter9drawImageERK6QRectFRK6QImageS2_6QFlagsIN2Qt19ImageConversionFlagEE() - 0x0000000061bf2660 # 14: Unable to obtain symbol # 15: ZN7QWidget5eventEP6QEvent() - 0x0000000001425ba0 # 16: ZN19QApplicationPrivate13notify_helperEP7QObjectP6QEvent() - 0x00000000013e7b70 # 17: ZN12QApplication6notifyEP7QObjectP6QEvent() - 0x00000000013ee990 # 18: ZN16QCoreApplication20sendSpontaneousEventEP7QObjectP6QEvent() - 0x0000000068a674f0 # 19: ZN14QWidgetPrivate14sendPaintEventERK7QRegion() - 0x000000000141e0f0 # 20: ZN14QWidgetPrivate10drawWidgetEP12QPaintDeviceRK7QRegionRK6QPointiP8QPainterP19QWidgetBackingStore() - 0x000000000141e150 # 21: ZN14QWidgetPrivate22paintSiblingsRecursiveEP12QPaintDeviceRK5QListIP7QObjectEiRK7QRegionRK6QPointiP8QPainterP19QWidgetBackingStore() - 0x000000000141f220 # 22: ZN14QWidgetPrivate22paintSiblingsRecursiveEP12QPaintDeviceRK5QListIP7QObjectEiRK7QRegionRK6QPointiP8QPainterP19QWidgetBackingStore() - 0x000000000141f220 # 23: ZN14QWidgetPrivate22paintSiblingsRecursiveEP12QPaintDeviceRK5QListIP7QObjectEiRK7QRegionRK6QPointiP8QPainterP19QWidgetBackingStore() - 0x000000000141f220 # 24: ZN14QWidgetPrivate22paintSiblingsRecursiveEP12QPaintDeviceRK5QListIP7QObjectEiRK7QRegionRK6QPointiP8QPainterP19QWidgetBackingStore() - 0x000000000141f220 # 25: ZN14QWidgetPrivate10drawWidgetEP12QPaintDeviceRK7QRegionRK6QPointiP8QPainterP19QWidgetBackingStore() - 0x000000000141e150 # 26: ZN14QWidgetPrivate22paintSiblingsRecursiveEP12QPaintDeviceRK5QListIP7QObjectEiRK7QRegionRK6QPointiP8QPainterP19QWidgetBackingStore() - 0x000000000141f220 # 27: ZN14QWidgetPrivate10drawWidgetEP12QPaintDeviceRK7QRegionRK6QPointiP8QPainterP19QWidgetBackingStore() - 0x000000000141e150 # 28: ZN14QWidgetPrivate11repaint_sysERK7QRegion() - 0x00000000013f41f0 # 29: ZN14QWidgetPrivate11repaint_sysERK7QRegion() - 0x00000000013f41f0 # 30: ZN14QWidgetPrivate16syncBackingStoreEv() - 0x000000000140d160 # 31: ZN7QWidget5eventEP6QEvent() - 0x0000000001425ba0 # 32: ZN11QMainWindow5eventEP6QEvent() - 0x0000000001513a50 # 33: ZN19QApplicationPrivate13notify_helperEP7QObjectP6QEvent() - 0x00000000013e7b70 # 34: ZN12QApplication6notifyEP7QObjectP6QEvent() - 0x00000000013ee990 # 35: ZN16QCoreApplication15notifyInternal2EP7QObjectP6QEvent() - 0x0000000068a66cc0 # 36: ZN23QCoreApplicationPrivate16sendPostedEventsEP7QObjectiP11QThreadData() - 0x0000000068a6d370 # 37: qt_plugin_instance() - 0x000000006a8f6eb0 # 38: ZN28QEventDispatcherWin32Private14sendTimerEventEi() - 0x0000000068ac1680 # 39: CallWindowProcW() - 0x00007fff427c6030 # 40: DispatchMessageW() - 0x00007fff427c5bf0 # 41: ZN21QEventDispatcherWin3213processEventsE6QFlagsIN10QEventLoop17ProcessEventsFlagEE() - 0x0000000068ac0b60 # 42: qt_plugin_instance() - 0x000000006a8f6eb0 # 43: ZN16QCoreApplication13processEventsE6QFlagsIN10QEventLoop17ProcessEventsFlagEEi() - 0x0000000068a67250 # 44: ZN5QTest5qWaitEi() - 0x0000000068ab7a20 # 45: Unable to obtain symbol # 46: Unable to obtain symbol # 47: Unable to obtain symbol # 48: Unable to obtain symbol # 49: Unable to obtain symbol # 50: Unable to obtain symbol # 51: ZNK11QMetaMethod6invokeEP7QObjectN2Qt14ConnectionTypeE22QGenericReturnArgument16QGenericArgumentS5_S5_S5_S5_S5_S5_S5_S5_S5_() - 0x0000000068a74760 # 52: ZN5QTest5qInitEP7QObjectiPPc() - 0x000000006edc7590 # 53: ZN5QTest5qInitEP7QObjectiPPc() - 0x000000006edc7590 # 54: ZN5QTest5qInitEP7QObjectiPPc() - 0x000000006edc7590 # 55: ZN5QTest4qRunEv() - 0x000000006edca280 # 56: ZN5QTest5qExecEP7QObjectiPPc() - 0x000000006edca670 # 57: Unable to obtain symbol # 58: Unable to obtain symbol # 59: Unable to obtain symbol # 60: BaseThreadInitThunk() - 0x00007fff44077bc0 # 61: RtlUserThreadStart() - 0x00007fff4476ceb0 The program has unexpectedly finished. The process was ended forcefully.
Any tips on how I could try and narrow down the issue?
There are mentions of threads and QPainter but I'm sure the issue is somehow related to loading a new file but I'm not sure how to get more information.
Cheers!
-
@rtavakko Your stack trace says that the exception was thrown in
QColorProfile::fromSRgb()
.This is a private class and method that was removed in Qt 5.13 -- perhaps you could try to upgrade to Qt 5.13 (or even Qt 5.14 beta) and see if the crash still occurs?
-
@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.
Cheers!
-
Update on this. I got the same crash in Qt 5.13.2 (Mingw 7.3.0 64-bit). I got a new crash in Qt 5.14.0 (same test conditions and crash happens the same way as before):
Exception address: 0x0000000061bc697c Exception code : 0xc0000005 Nearby symbol : ZN12QColorTrcLut17fromTransferTableERK19QColorTransferTable Stack: # 1: ZN5QTest15toPrettyUnicodeEPKti() - 0x000000006edc27a0 # 2: UnhandledExceptionFilter() - 0x00007ff9f924f490 # 3: memset() - 0x00007ff9fbc82fc0 # 4: _C_specific_handler() - 0x00007ff9fbc6c640 # 5: _chkstk() - 0x00007ff9fbc810e0 # 6: RtlRaiseException() - 0x00007ff9fbc49ef0 # 7: KiUserExceptionDispatcher() - 0x00007ff9fbc7fe40 # 8: ZN12QColorTrcLut17fromTransferTableERK19QColorTransferTable() - 0x0000000061b4b770 # 9: ZN13QVulkanWindow11qt_metacallEN11QMetaObject4CallEiPPv() - 0x0000000061dbb980 # 10: ZN12QColorTrcLut17fromTransferTableERK19QColorTransferTable() - 0x0000000061b4b770 # 11: ZrsR11QDataStreamR8QPolygon() - 0x0000000061c60140 # 12: ZN18QRasterPaintEngine4clipERK11QVectorPathN2Qt13ClipOperationE() - 0x0000000061c0ff20 # 13: ZN8QPainter9drawImageERK6QRectFRK6QImageS2_6QFlagsIN2Qt19ImageConversionFlagEE() - 0x0000000061c29840 # 14: Unable to obtain symbol # 15: ZN7QWidget5eventEP6QEvent() - 0x00000000012452f0 # 16: ZN19QApplicationPrivate13notify_helperEP7QObjectP6QEvent() - 0x0000000001207ae0 # 17: ZN12QApplication6notifyEP7QObjectP6QEvent() - 0x000000000120e7f0 # 18: ZN16QCoreApplication20sendSpontaneousEventEP7QObjectP6QEvent() - 0x0000000068a7dc40 # 19: ZN14QWidgetPrivate14sendPaintEventERK7QRegion() - 0x000000000123d310 # 20: ZN14QWidgetPrivate10drawWidgetEP12QPaintDeviceRK7QRegionRK6QPoint6QFlagsINS_14DrawWidgetFlagEEP8QPainterP21QWidgetRepaintManager() - 0x000000000123d370 # 21: ZN14QWidgetPrivate22paintSiblingsRecursiveEP12QPaintDeviceRK5QListIP7QObjectEiRK7QRegionRK6QPoint6QFlagsINS_14DrawWidgetFlagEEP8QPainterP21QWidgetRepaintManager() - 0x000000000123eb50 # 22: ZN14QWidgetPrivate22paintSiblingsRecursiveEP12QPaintDeviceRK5QListIP7QObjectEiRK7QRegionRK6QPoint6QFlagsINS_14DrawWidgetFlagEEP8QPainterP21QWidgetRepaintManager() - 0x000000000123eb50 # 23: ZN14QWidgetPrivate22paintSiblingsRecursiveEP12QPaintDeviceRK5QListIP7QObjectEiRK7QRegionRK6QPoint6QFlagsINS_14DrawWidgetFlagEEP8QPainterP21QWidgetRepaintManager() - 0x000000000123eb50 # 24: ZN14QWidgetPrivate22paintSiblingsRecursiveEP12QPaintDeviceRK5QListIP7QObjectEiRK7QRegionRK6QPoint6QFlagsINS_14DrawWidgetFlagEEP8QPainterP21QWidgetRepaintManager() - 0x000000000123eb50 # 25: ZN14QWidgetPrivate10drawWidgetEP12QPaintDeviceRK7QRegionRK6QPoint6QFlagsINS_14DrawWidgetFlagEEP8QPainterP21QWidgetRepaintManager() - 0x000000000123d370 # 26: ZN14QWidgetPrivate22paintSiblingsRecursiveEP12QPaintDeviceRK5QListIP7QObjectEiRK7QRegionRK6QPoint6QFlagsINS_14DrawWidgetFlagEEP8QPainterP21QWidgetRepaintManager() - 0x000000000123eb50 # 27: ZN14QWidgetPrivate10drawWidgetEP12QPaintDeviceRK7QRegionRK6QPoint6QFlagsINS_14DrawWidgetFlagEEP8QPainterP21QWidgetRepaintManager() - 0x000000000123d370 # 28: ZNK14QWidgetPrivate24shouldDiscardSyncRequestEv() - 0x00000000012133a0 # 29: ZNK14QWidgetPrivate24shouldDiscardSyncRequestEv() - 0x00000000012133a0 # 30: ZN14QWidgetPrivate16syncBackingStoreEv() - 0x000000000123e9e0 # 31: ZN7QWidget5eventEP6QEvent() - 0x00000000012452f0 # 32: ZN11QMainWindow5eventEP6QEvent() - 0x0000000001338e70 # 33: ZN19QApplicationPrivate13notify_helperEP7QObjectP6QEvent() - 0x0000000001207ae0 # 34: ZN12QApplication6notifyEP7QObjectP6QEvent() - 0x000000000120e7f0 # 35: ZN16QCoreApplication15notifyInternal2EP7QObjectP6QEvent() - 0x0000000068a7d410 # 36: ZN23QCoreApplicationPrivate16sendPostedEventsEP7QObjectiP11QThreadData() - 0x0000000068a83440 # 37: qt_plugin_instance() - 0x000000006a8fbe40 # 38: ZN21QEventDispatcherWin3213processEventsE6QFlagsIN10QEventLoop17ProcessEventsFlagEE() - 0x0000000068ad8cb0 # 39: qt_plugin_instance() - 0x000000006a8fbe40 # 40: ZN16QCoreApplication13processEventsE6QFlagsIN10QEventLoop17ProcessEventsFlagEEi() - 0x0000000068a7d9a0 # 41: ZN5QTest5qWaitEi() - 0x0000000068acfbe0 # 42: Unable to obtain symbol # 43: Unable to obtain symbol # 44: Unable to obtain symbol # 45: Unable to obtain symbol # 46: Unable to obtain symbol # 47: Unable to obtain symbol # 48: ZNK11QMetaMethod6invokeEP7QObjectN2Qt14ConnectionTypeE22QGenericReturnArgument16QGenericArgumentS5_S5_S5_S5_S5_S5_S5_S5_S5_() - 0x0000000068a8b460 # 49: ZN5QTest5qInitEP7QObjectiPPc() - 0x000000006edc88d0 # 50: ZN5QTest5qInitEP7QObjectiPPc() - 0x000000006edc88d0 # 51: ZN5QTest5qInitEP7QObjectiPPc() - 0x000000006edc88d0 # 52: ZN5QTest4qRunEv() - 0x000000006edcb5c0 # 53: ZN5QTest5qExecEP7QObjectiPPc() - 0x000000006edcb9b0 # 54: Unable to obtain symbol # 55: Unable to obtain symbol # 56: Unable to obtain symbol # 57: BaseThreadInitThunk() - 0x00007ff9faab7bc0 # 58: RtlUserThreadStart() - 0x00007ff9fbc4ceb0
-
@rtavakko said in OpenCV VideoCapture Failure from QThread:
Aaah so 'Nearby Symbol' is where it occured and 'Exception Code' is what the error was.
Yep. And the stack trace shows the calls leading up to the crash, in reverse order.
- In Qt 5.12 you had:
QVulkanWindow::qt_metacall(...)
->QColorProfile::fromSRgb()
-> crash - In Qt 5.14 you had:
QVulkanWindow::qt_metacall(...)
->QColorTrcLut::fromTransferTable()
-> 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.
You can just run your debugger without using Qt Test: https://doc.qt.io/qtcreator/creator-debugging.html It is useful for locating "simple" coding errors like trying to read beyond the last element of an array.
However, in your situation, you get a memory access violation error (https://stackoverflow.com/questions/5303524/what-exactly-is-the-scope-of-access-violation-0xc0000005 ) when loading many files quickly but doesn't crash when loading slowly, is that right? In this situation, the debugger is less useful. I'm guessing that when you have many threads loading at the same time, one of the threads could be corrupting the memory used by another thread and this corruption is detected during the colour lookup (https://code.woboq.org/qt5/qtbase/src/gui/painting/qcolortrclut.cpp.html#_ZN12QColorTrcLut17fromTransferTableERK19QColorTransferTable ). The corruption was probably not caused by the colour lookup function itself.
I don't know of a good way to debug threading issues in Windows. If you can build your project in Linux, Valgrind might help.
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.
I don't think libpng is used to load videos. Is your program loading any images?
- In Qt 5.12 you had:
-
@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.
//Show current image data void Display::updateImage(const uchar *imageData, int width, int height, int step) { if(imageData != nullptr) { displayImage = QImage(imageData, width, height, step, QImage::Format_RGBA8888); update(); } } //Paint event for display object void Display::paintEvent(QPaintEvent*) { QPainter painter(this); painter.setRenderHint(QPainter::SmoothPixmapTransform,true); painter.setPen(QPen(Qt::red)); painter.drawImage(rect(),displayImage); //Resize the image based on widget size and display it }
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.
Cheers!
-
@rtavakko said in OpenCV VideoCapture Failure from QThread:
it seems the crash happens only when I emit a signal containing an OpenCV matrix data pointer
I don't have much experience with OpenCV, but you might need to be extra careful when passing
cv::mat
across different threads: https://stackoverflow.com/questions/10657841/is-cvmat-thread-safe-atomic-assignment-refcountingI don't see what in here could be causing a crash specially given that I use a const pointer.
The code you posted does not show how you use
cv::mat
or how you emit your signal.Is there a way I could catch the exception when it happens if I can't get to the bottom of the issue?
Not really. Multithreading-related memory problems cause damage long before the access violation exception is generated.
-
Hi,
@rtavakko said in OpenCV VideoCapture Failure from QThread:
void Display::updateImage(const uchar *imageData, int width, int height, int step)
{
if(imageData != nullptr)
{
displayImage = QImage(imageData, width, height, step, QImage::Format_RGBA8888);
update();
}
}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.
-
@JKSH This is how I emit the OpenCV mat data:
emit processedImage(2, videoFrameOut.ptr(0,0),videoFrameOut.cols, videoFrameOut.rows, videoFrameOut.step);
The first parameter is just used to determine which display should draw the image and the rest are dimensions and stride which I think are ok.
@SGaist You are correct, I changed the line below to make a copy:
displayImage = QImage(imageData, width, height, step, QImage::Format_RGBA8888).copy(0,0,width,height);
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.
Thanks!