Details
-
Bug
-
Resolution: Done
-
P1: Critical
-
5.5.1
-
None
-
5e3f770ad5e47f296b4782c0b6c5b03162027500
Description
The following program dumps core in the QString copy constructor. The problem is triggered by QtConcurrent::run() using the current thread and the functor throwing an exception:
#include <QCoreApplication> #include <QException> #include <QRunnable> #include <QString> #include <QThreadPool> #include <QtConcurrent> #include <chrono> #include <thread> class SlowTask : public QRunnable { void run() override { std::this_thread::sleep_for(std::chrono::seconds(10)); } }; // Any return type with a copy constructor should do QString foo() { throw QException(); } int main(int argc, char **argv) { QCoreApplication app(argc, argv); // Fill up the thread pool with slow tasks for (int i = 0; i < 100; i++) { QThreadPool::globalInstance()->start(new SlowTask); } // Since the thread pool is busy, this should force // stealAndRunRunnable() to execute the function in the current // thread. try { QtConcurrent::run(foo).result(); } catch (QException const&) { /* nothing */ } }
The problem appears to be caused by QFutureInterfaceBase::waitForResult(), which returns early in this case, without calling throwPossibleException(), so QFuture::result() ends up dereferencing a nullptr when it calls the copy constructor for the return type of the functor.
My thanks to James Henstridge for the stand-alone test case!