Background
In my Qt5.3 application I deal with several time consuming processes (statistical computations). In order to be able to operate with application, while one or more computations are running, I created class called ProgressManager. This manager registers computation objects that inherit from abstract class IRunnable and implement pure virtual method run.
Each time a new time-consuming operation is started, it is registered in ProgressManager connected to its progressbar and started through following function:
void ProgressManager::runProgress(const QVariant &id, const QVariant ¶m) {
// If progress is not present, exit
if (!progs.contains(id)) {
return;
}
// If progress is not runnable, exit
IRunnable* runnable = dynamic_cast<IRunnable*>(progs.value(id));
if (!runnable) {
return;
}
// Create future watcher
QFutureWatcher<QVariant>* watcher = new QFutureWatcher<QVariant>();
connect(watcher, SIGNAL(finished()), this, SLOT(handleFinished()));
// Register running progress
running.insert(watcher, id);
// Paralelize runnable progress
QFuture<QVariant> future = QtConcurrent::run(runnable, &IRunnable::run, param);
watcher->setFuture(future);
}
After parallel process finishes following function should be called:
void ProgressManager::handleFinished() {
// Retrieves sender watcher
QObject* s = this->sender();
QFutureWatcher<QVariant>* w = dynamic_cast<QFutureWatcher<QVariant>*>(s);
// Retrieve ID of running progress and delete watcher
QVariant id = running.value(w);
running.remove(w);
delete w;
// Emit progress has finished
emit finished(id);
}
Problem
Everything is running smoothly until end of paralelized process is reached. Then application crashes everytime with segmentation fault, before calling finished signal and handleFinished slots.
Crash is reported in file qfutureinterface.h in function reportResults on line 211 where function is reportResultsReady called:
194 template <typename T>
195 inline void QFutureInterface<T>::reportResult(const T *result, int index)
196 {
197 QMutexLocker locker(mutex());
198 if (this->queryState(Canceled) || this->queryState(Finished)) {
199 return;
200 }
201
202 QtPrivate::ResultStore<T> &store = resultStore();
203
204
205 if (store.filterMode()) {
206 const int resultCountBefore = store.count();
207 store.addResult(index, result);
208 this->reportResultsReady(resultCountBefore, resultCountBefore + store.count());
209 } else {
210 const int insertIndex = store.addResult(index, result);
211 this->reportResultsReady(insertIndex, insertIndex + 1);
212 }
213 }