Fix crash when closing export dialog while export is running
TaskDialog::closeEvent() was calling deleteLater() immediately when the user closed the window. The ExportTask was a child QObject of the dialog, so it got destroyed while its Run() method was still executing in the worker thread, leading to a use-after-free on encoder_->Close(). Defer deletion until the QFutureWatcher reports that the task has actually finished. A new task_finished_ flag tracks this so closeEvent only deletes when it is safe, and TaskFinished() closes the dialog (which now deletes instead of calling close() again while the task is still alive).
This commit is contained in:
@@ -34,6 +34,7 @@ TaskDialog::TaskDialog(Task *task, const QString &title, QWidget *parent)
|
||||
, task_(task)
|
||||
, destroy_on_close_(true)
|
||||
, already_shown_(false)
|
||||
, task_finished_(false)
|
||||
{
|
||||
// Clear task when this dialog is destroyed
|
||||
task_->setParent(this);
|
||||
@@ -84,8 +85,11 @@ void TaskDialog::closeEvent(QCloseEvent *e)
|
||||
// Reset shown
|
||||
already_shown_ = false;
|
||||
|
||||
// Clean up this task and dialog
|
||||
if (destroy_on_close_) {
|
||||
// Clean up this task and dialog, but only if the task has actually finished.
|
||||
// If the user closes the window while the task is still running, deleting now
|
||||
// would destroy the Task object out from under the worker thread and crash
|
||||
// when the task later touches its own members (e.g. ExportTask::encoder_).
|
||||
if (destroy_on_close_ && task_finished_) {
|
||||
deleteLater();
|
||||
}
|
||||
}
|
||||
@@ -95,6 +99,8 @@ void TaskDialog::TaskFinished()
|
||||
QFutureWatcher<bool> *task_watcher =
|
||||
static_cast<QFutureWatcher<bool> *>(sender());
|
||||
|
||||
task_finished_ = true;
|
||||
|
||||
if (task_watcher->result()) {
|
||||
emit TaskSucceeded(task_);
|
||||
} else {
|
||||
|
||||
@@ -75,6 +75,8 @@ private:
|
||||
|
||||
bool already_shown_;
|
||||
|
||||
bool task_finished_;
|
||||
|
||||
private slots:
|
||||
void TaskFinished();
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user