Mysterious QMutex destroying locked mutex
-
Indeed it has:
class ThumbnailExtractor : public QObject { Q_OBJECT .... private: QMediaPlayer *player; ThumbailVideoSurface *surface; QMediaContent content;//that's not a descendant of QObject ..... };
however, in the constructor I have:
ThumbnailExtractor::ThumbnailExtractor(int counter, const QString &videoFilePath, QObject *parent) : QObject(parent), content(videoFilePath) { player = new QMediaPlayer(this); surface = new ThumbailVideoSurface(counter, this); player->setVideoOutput(surface); connect(surface, SIGNAL(stopMedia()), player, SLOT(stop()), Qt::QueuedConnection); connect(surface, SIGNAL(stopMedia()), this, SIGNAL(finished()), Qt::QueuedConnection); player->setMuted(true); connect(player, SIGNAL(error(QMediaPlayer::Error)), this, SLOT(error(QMediaPlayer::Error)));//, Qt::QueuedConnection); connect(player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)), this, SLOT(mediaStatusChanged(QMediaPlayer::MediaStatus)));//, Qt::QueuedConnection); }
so yeah, these should be moved to another thread along with ThumbnailExtractor object.
-
@MasterBLB said in Mysterious QMutex destroying locked mutex:
so yeah, these should be moved to another thread along with ThumbnailExtractor object.
What about
ThumbailVideoSurface
? -
@KroMignon said in Mysterious QMutex destroying locked mutex:
@MasterBLB said in Mysterious QMutex destroying locked mutex:
so yeah, these should be moved to another thread along with ThumbnailExtractor object.
What about
ThumbailVideoSurface
?It does not contain any member variables.
EDIT:
Wrong! It has just one int member; I meant it does not contain any QObject-related members. -
@MasterBLB said in Mysterious QMutex destroying locked mutex:
it does not contain any QObject-related members.
Given the name, are you by any chance using
QPixmap
in it?From https://doc.qt.io/qt-5/thread-basics.html#gui-thread-and-worker-thread
All widgets and several related classes, for example QPixmap, don't work in secondary threads.
-
I'm using QImage:
bool ThumbailVideoSurface::present(const QVideoFrame &frame) { if (frame.isValid()) { QImage thumbnail(frame.image()); thumbnail.save("thumbnail" + QString::number(tempCounter) + ".png");//that's only temporary, finally I'm going to create some kind of QMap <fileName, thumbnail QPixmap/QImage> //stop();//to wykrzacza aplikacjÄ™ emit stopMedia(); } return true; }
but I was going to switch to QPixmap later on, for rescaling the image.
-
@MasterBLB said in Mysterious QMutex destroying locked mutex:
ThumbnailExtractor is not using QMutex at all, the crashing one comes from QThread. What I've messed up?
You don't wait for the thread to finish from what I can tell. Also when diagnosing crashes, please provide a stack trace.
-
A try to check stack frame was the 1st I've tried before writing the post, sadly there is none. Besides, pls explain me how I don't wait for the thread to stop before deleting if I have the lines:
connect(extractor, SIGNAL(finished()), thread, SLOT(quit()), Qt::QueuedConnection); connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
-
@MasterBLB said in Mysterious QMutex destroying locked mutex:
A try to check stack frame was the 1st I've tried before writing the post, sadly there is none.
If you don't have a stack trace, then the program is not running. There's no crash without a stack is the point. If you simply get a warning from the Qt runtime, then run your program in the debuger with the environment variable
QT_FATAL_WARNINGS
set to1
so it trips at the point of the actual error and then extract the stack trace.Besides, pls explain me how I don't wait for the thread to stop before deleting if I have the lines:
QThread::wait
(equivalent tostd::thread::join
) comes to mind. The fact that a signal was raised doesn't mean that the thread (which is simply a 'special' function) has finished executing. -
@kshegunov said in Mysterious QMutex destroying locked mutex:
If you don't have a stack trace, then the program is not running. There's no crash without a stack is the point. If you simply get a warning from the Qt runtime, then run your program in the debuger with the environment variable QT_FATAL_WARNINGS set to 1 so it trips at the point of the actual error and then extract the stack trace.
I mean there is no readable/useful stack frame, neither I don't know which of over 100 threads listed in debugger is the one I should check.
I tried that QT_FATAL_WARNINGS before, sadly due to some crap with QML ("QML QQuickText: Detected anchors on an item that is managed by a layout. This is undefined behavior; use Layout.alignment instead.") I won't even reach the code part which contains threads.
-
Humor me, will you?
constexpr int poolSize = 16; QVector<QThread *> threadPool(poolSize); QCoreApplication * app = QCoreApplication::instance(); for (size_t i = 0; i < poolSize; i++) { QThread * thread = new QThread(app); thread->start(); QObject::connect(thread, &QThread::finished, thread, &QThread::deleteLater); } QObject::connect(app, &QCoreApplication::aboutToQuit, [threadPool] () -> void { for (QThread * thread : threadPool) { thread->quit(); thread->wait(); } }); int index = 0; for (const QString &video : videoFiles) { ThumbnailExtractor *extractor = new ThumbnailExtractor(counter, folderPath + '/' + video); extractor->moveToThread(threadPool[index++ % poolSize]); QObject::connect(extractor, &ThumbnailExtractor::finished, extractor, &QObject::deleteLater); QMetaObject::invokeMethod(extractor, &ThumbnailExtractor::generateThumbnail, Qt::QueuedConnection); }
A note here:
QMediaPlayer
and related classes don't seem to be reentrant so you can't use them from different threads. Stick to the main one.