forked from qt-creator/qt-creator
QmlProfiler: Avoid race conditions when loading or saving data
We cannot assume that the model manager is still available when the operation finishes. Also, accessing the QML model or the trace time from the thread is dangerous. Change-Id: I673c57c09490a0e3e2647f3197929eff1ce4ceb3 Reviewed-by: Eike Ziller <eike.ziller@theqtcompany.com>
This commit is contained in:
@@ -338,16 +338,20 @@ void QmlProfilerModelManager::save(const QString &filename)
|
||||
|
||||
d->notesModel->saveData();
|
||||
|
||||
QFuture<void> result = Utils::runAsync<void>([this, file] (QFutureInterface<void> &future) {
|
||||
QmlProfilerFileWriter writer;
|
||||
writer.setTraceTime(traceTime()->startTime(), traceTime()->endTime(),
|
||||
traceTime()->duration());
|
||||
writer.setQmlEvents(d->model->getEventTypes(), d->model->getEvents());
|
||||
writer.setNotes(d->model->getEventNotes());
|
||||
writer.setFuture(&future);
|
||||
writer.save(file);
|
||||
QmlProfilerFileWriter *writer = new QmlProfilerFileWriter(this);
|
||||
writer->setTraceTime(traceTime()->startTime(), traceTime()->endTime(),
|
||||
traceTime()->duration());
|
||||
writer->setQmlEvents(d->model->getEventTypes(), d->model->getEvents());
|
||||
writer->setNotes(d->model->getEventNotes());
|
||||
|
||||
connect(writer, &QObject::destroyed, this, &QmlProfilerModelManager::saveFinished,
|
||||
Qt::QueuedConnection);
|
||||
|
||||
QFuture<void> result = Utils::runAsync<void>([file, writer] (QFutureInterface<void> &future) {
|
||||
writer->setFuture(&future);
|
||||
writer->save(file);
|
||||
delete writer;
|
||||
file->deleteLater();
|
||||
QMetaObject::invokeMethod(this, "saveFinished", Qt::QueuedConnection);
|
||||
});
|
||||
|
||||
Core::ProgressManager::addTask(result, tr("Saving Trace Data"), Constants::TASK_SAVE,
|
||||
@@ -366,24 +370,33 @@ void QmlProfilerModelManager::load(const QString &filename)
|
||||
|
||||
clear();
|
||||
setState(AcquiringData);
|
||||
QmlProfilerFileReader *reader = new QmlProfilerFileReader(this);
|
||||
|
||||
QFuture<void> result = Utils::runAsync<void>([this, file] (QFutureInterface<void> &future) {
|
||||
QmlProfilerFileReader reader;
|
||||
reader.setFuture(&future);
|
||||
connect(&reader, &QmlProfilerFileReader::error, this, &QmlProfilerModelManager::error);
|
||||
reader.setQmlDataModel(d->model);
|
||||
reader.load(file);
|
||||
setRecordedFeatures(reader.loadedFeatures());
|
||||
connect(reader, &QmlProfilerFileReader::error, this, [this, reader](const QString &message) {
|
||||
delete reader;
|
||||
emit error(message);
|
||||
}, Qt::QueuedConnection);
|
||||
|
||||
connect(reader, &QmlProfilerFileReader::success, this, [this, reader]() {
|
||||
d->model->setData(reader->traceStart(), qMax(reader->traceStart(), reader->traceEnd()),
|
||||
reader->qmlEvents(), reader->ranges());
|
||||
d->model->setNoteData(reader->notes());
|
||||
setRecordedFeatures(reader->loadedFeatures());
|
||||
d->traceTime->increaseEndTime(d->model->lastTimeMark());
|
||||
delete reader;
|
||||
acquiringDone();
|
||||
}, Qt::QueuedConnection);
|
||||
|
||||
QFuture<void> result = Utils::runAsync<void>([file, reader] (QFutureInterface<void> &future) {
|
||||
reader->setFuture(&future);
|
||||
reader->load(file);
|
||||
file->close();
|
||||
file->deleteLater();
|
||||
d->traceTime->increaseEndTime(d->model->lastTimeMark());
|
||||
acquiringDone();
|
||||
});
|
||||
|
||||
Core::ProgressManager::addTask(result, tr("Loading Trace Data"), Constants::TASK_LOAD);
|
||||
}
|
||||
|
||||
|
||||
void QmlProfilerModelManager::setState(QmlProfilerModelManager::State state)
|
||||
{
|
||||
// It's not an error, we are continuously calling "AcquiringData" for example
|
||||
|
||||
Reference in New Issue
Block a user