App hangs in QPixmap::fromImage
-
Hi,
I'm using a Qt app to display video stream from a grayscale devicealab camera. Images are displayed in a QGraphicsView using QPixmap. For some reason app randomly gets stuck in QPixmap::fromImage!
Environment:
Qt 5.15.0 msvc2019 x64Execution flow:
- acquire images in camera thread
- in UI thread, at refresh rate make a copy of image buffer, then create a QImage from buffer data
- create QPixmap from QImage
- set QPixmap to a QGraphicsPixmapItem
Call stack:
Using Qt's dlls with pdb I see that Qt waits for a semaphore to be released after image buffer conversion:
Image conversion:
From what I see in Qt codebase, the convert_generic function uses a thread pool to perform image buffer conversion. One of the threads doesn't release the semaphore so UI hangs.Any help greatly appreciated.
Thanks -
@mpouchol said in App hangs in QPixmap::fromImage:
in UI thread, at refresh rate make a copy of image buffer, then create a QImage from buffer data
Hello and welcome.
May not be the issue/relevant, but just checking: how do you "make a copy of image buffer" safely, given that camera thread is updating image buffer? Is that code thread-safe?
-
Look in your other threads where you also try to convert a QImage and hang somewhere near convert_generic()
-
@Christian-Ehrlicher the QImage to QPixmap conversion is only done in the main/UI thread.
-
@mpouchol said in App hangs in QPixmap::fromImage:
the QImage to QPixmap conversion is only done in the main/UI thread.
This does not what I've suggested... go through your other threads and take a look what they're doing and if there's another one in this function.
-
@Christian-Ehrlicher thanks for your suggestion. I'm not sure to understand what I should do.
The convert_generic function is actually one of the function called by QPixmap::fromImage as you can see in the callstack attached to my question.
The app is stuck in this function trying to acquire a semaphore. -
Is your QImage good? Does saving the QImage to a file work? What is the QImage::Format of the image?
-
It works most of the time and hangs randomly. It can take somewhere between a few seconds and a 1-2 hours to hang. Images are fetched from camera at around 60fps and each frame should be the same size. I suspect data gets corrupted somewhere but I was expecting a crash instead of an app freeze. It's a bit strange that it always hang at the same point.
-
Again: it hangs on a mutex lock - nothing to do with the data. Take a look if this mutex is locked in another thread...
-
@Christian-Ehrlicher the mutex is owned by Qt code inside
QPixmap::fromImage
I don't use this function from other threads so I don't see what I did that caused it to stay locked. -
@mpouchol said in App hangs in QPixmap::fromImage:
I don't use this function from other threads so I don't see what I did that caused it to stay locked.
I'm giving up... looks like it's too hard to look into the other threads while it is hanging to see if another thread is also using this mutex. So try to figure it out by your own.
-
@Christian-Ehrlicher said in App hangs in QPixmap::fromImage:
I'm giving up... looks like it's too hard to look into the other threads
I did that and that's not the case. Thanks for your help anyway.
-
Ok, taking a deeper look into convert_generic() the qimage is converted with more than one thread. One of these subthreads hangs maybe due to a broken QImage. Look into your other threads to see which one is somewhere hanging inside convertSegment()
-
I also had a look at the code inside
convert_generic()
. When the main thread is frozen I don't see other threads hanging inconvertSegment
which make me think that maybe one of the convertSegment threads has died silently and is not releasing the semaphore inconvert_generic
because I don't see visual studio raising exceptions in other threads. -
If you compile Qt by your own build a big try/catch block around convert_segment and simply catch all exceptions to see if there is one.
You can also create a helper thread which writes out the current qimage after a certain period of time when it was not canceled in between so you can inspect the qimage.