Details
-
Bug
-
Resolution: Done
-
P2: Important
-
4.7.2
-
None
-
383da4084ae0cd8dcb9777cbfa90a55c56f7ad09
Description
If QFutures are used in destructors or in functions called from destructors, and if those destructors are called because an exception has been thrown and stack unwinding is in progress, the QFutures do not throw exceptions they themselves contain. This is not mentioned in QFuture's or QtConcurrent::Exception's documentation. What's more, this behaviour is potentially dangerous, since functions may not know they are called from a destructor and thus expect QFtutures to raise exceptions they themselves catch and handle.
Current behaviour happens because QtConcurrent::internal::ExceptionStore::throwPossibleException() uses std::uncaught_exception() to check whether an exception has already been thrown, and chooses not to throw exceptions in that case. I suspect this is because this might result in two simultaneous competing exceptions which leads to program termination. However, it is safe to throw an exception even if another exception has been thrown. It's just necessary to catch and handle the second exception before it ends up on the same level as the first exception.
A comment in throwPossibleException() says: "On win32-g+, with GCC 3.4.2 std::uncaught_exception() isn't reliable." The problem mentioned in this report is caused by std::uncaught_exception() as defined in the C+ standard, and is not caused by any specific compiler or platform.
Either QFutures should be allowed to throw exceptions even if other exceptions have already been thrown, or QFuture's (and QtConcurrent::Exception's) documentation should be changed to mention the limitation.
(Problems caused by std::uncaught_exception() are discussed in http://www.gotw.ca/gotw/047.htm , for example)
Attached is a modified version of http://doc.qt.nokia.com/4.7/qtconcurrent-map.html demonstrating the problem.