Qt: fix random segfaults when canceling batch operations

It occasionally happened that the progress_dialog object was deleted before we reached the end of the function.
This commit is contained in:
Megamouse 2023-11-25 03:18:26 +01:00
parent b774ba9888
commit ac869ec855
3 changed files with 85 additions and 44 deletions

View file

@ -1927,7 +1927,7 @@ void game_list_frame::BatchCreateCPUCaches()
const QString main_label = tr("Creating all LLVM caches"); const QString main_label = tr("Creating all LLVM caches");
progress_dialog* pdlg = new progress_dialog(tr("LLVM Cache Batch Creation"), main_label, tr("Cancel"), 0, total, true, this); progress_dialog* pdlg = new progress_dialog(tr("LLVM Cache Batch Creation"), main_label, tr("Cancel"), 0, total, false, this);
pdlg->setWindowFlags(Qt::Window | Qt::WindowMinimizeButtonHint); pdlg->setWindowFlags(Qt::Window | Qt::WindowMinimizeButtonHint);
pdlg->setAutoClose(false); pdlg->setAutoClose(false);
pdlg->setAutoReset(false); pdlg->setAutoReset(false);
@ -1978,24 +1978,17 @@ void game_list_frame::BatchCreateCPUCaches()
if (pdlg->wasCanceled() || g_system_progress_canceled) if (pdlg->wasCanceled() || g_system_progress_canceled)
{ {
game_list_log.notice("PPU Cache Batch Creation was canceled"); pdlg->deleteLater(); // We did not allow deletion earlier to prevent segfaults when canceling.
game_list_log.notice("LLVM Cache Batch Creation was canceled");
if (!Emu.IsStopped()) Emu.GracefulShutdown(false);
{ }
QApplication::processEvents(); else
Emu.GracefulShutdown(false); {
} pdlg->SetDeleteOnClose();
pdlg->setLabelText(tr("Created LLVM Caches for %n title(s)", "", created));
if (!pdlg->wasCanceled()) pdlg->setCancelButtonText(tr("OK"));
{ QApplication::beep();
pdlg->close();
}
return;
} }
pdlg->setLabelText(tr("Created PPU Caches for %n title(s)", "", created));
pdlg->setCancelButtonText(tr("OK"));
QApplication::beep();
} }
void game_list_frame::BatchRemovePPUCaches() void game_list_frame::BatchRemovePPUCaches()
@ -2018,7 +2011,7 @@ void game_list_frame::BatchRemovePPUCaches()
return; return;
} }
progress_dialog* pdlg = new progress_dialog(tr("PPU Cache Batch Removal"), tr("Removing all PPU caches"), tr("Cancel"), 0, total, true, this); progress_dialog* pdlg = new progress_dialog(tr("PPU Cache Batch Removal"), tr("Removing all PPU caches"), tr("Cancel"), 0, total, false, this);
pdlg->setAutoClose(false); pdlg->setAutoClose(false);
pdlg->setAutoReset(false); pdlg->setAutoReset(false);
pdlg->show(); pdlg->show();
@ -2028,7 +2021,6 @@ void game_list_frame::BatchRemovePPUCaches()
{ {
if (pdlg->wasCanceled()) if (pdlg->wasCanceled())
{ {
game_list_log.notice("PPU Cache Batch Removal was canceled");
break; break;
} }
QApplication::processEvents(); QApplication::processEvents();
@ -2039,9 +2031,18 @@ void game_list_frame::BatchRemovePPUCaches()
} }
} }
pdlg->setLabelText(tr("%0/%1 caches cleared").arg(removed).arg(total)); if (pdlg->wasCanceled())
pdlg->setCancelButtonText(tr("OK")); {
QApplication::beep(); pdlg->deleteLater(); // We did not allow deletion earlier to prevent segfaults when canceling.
game_list_log.notice("PPU Cache Batch Removal was canceled");
}
else
{
pdlg->SetDeleteOnClose();
pdlg->setLabelText(tr("%0/%1 caches cleared").arg(removed).arg(total));
pdlg->setCancelButtonText(tr("OK"));
QApplication::beep();
}
} }
void game_list_frame::BatchRemoveSPUCaches() void game_list_frame::BatchRemoveSPUCaches()
@ -2064,7 +2065,7 @@ void game_list_frame::BatchRemoveSPUCaches()
return; return;
} }
progress_dialog* pdlg = new progress_dialog(tr("SPU Cache Batch Removal"), tr("Removing all SPU caches"), tr("Cancel"), 0, total, true, this); progress_dialog* pdlg = new progress_dialog(tr("SPU Cache Batch Removal"), tr("Removing all SPU caches"), tr("Cancel"), 0, total, false, this);
pdlg->setAutoClose(false); pdlg->setAutoClose(false);
pdlg->setAutoReset(false); pdlg->setAutoReset(false);
pdlg->show(); pdlg->show();
@ -2074,7 +2075,6 @@ void game_list_frame::BatchRemoveSPUCaches()
{ {
if (pdlg->wasCanceled()) if (pdlg->wasCanceled())
{ {
game_list_log.notice("SPU Cache Batch Removal was canceled. %d/%d folders cleared", removed, total);
break; break;
} }
QApplication::processEvents(); QApplication::processEvents();
@ -2085,9 +2085,18 @@ void game_list_frame::BatchRemoveSPUCaches()
} }
} }
pdlg->setLabelText(tr("%0/%1 caches cleared").arg(removed).arg(total)); if (pdlg->wasCanceled())
pdlg->setCancelButtonText(tr("OK")); {
QApplication::beep(); pdlg->deleteLater(); // We did not allow deletion earlier to prevent segfaults when canceling.
game_list_log.notice("SPU Cache Batch Removal was canceled. %d/%d folders cleared", removed, total);
}
else
{
pdlg->SetDeleteOnClose();
pdlg->setLabelText(tr("%0/%1 caches cleared").arg(removed).arg(total));
pdlg->setCancelButtonText(tr("OK"));
QApplication::beep();
}
} }
void game_list_frame::BatchRemoveCustomConfigurations() void game_list_frame::BatchRemoveCustomConfigurations()
@ -2108,7 +2117,7 @@ void game_list_frame::BatchRemoveCustomConfigurations()
return; return;
} }
progress_dialog* pdlg = new progress_dialog(tr("Custom Configuration Batch Removal"), tr("Removing all custom configurations"), tr("Cancel"), 0, total, true, this); progress_dialog* pdlg = new progress_dialog(tr("Custom Configuration Batch Removal"), tr("Removing all custom configurations"), tr("Cancel"), 0, total, false, this);
pdlg->setAutoClose(false); pdlg->setAutoClose(false);
pdlg->setAutoReset(false); pdlg->setAutoReset(false);
pdlg->show(); pdlg->show();
@ -2118,7 +2127,6 @@ void game_list_frame::BatchRemoveCustomConfigurations()
{ {
if (pdlg->wasCanceled()) if (pdlg->wasCanceled())
{ {
game_list_log.notice("Custom Configuration Batch Removal was canceled. %d/%d custom configurations cleared", removed, total);
break; break;
} }
QApplication::processEvents(); QApplication::processEvents();
@ -2129,9 +2137,19 @@ void game_list_frame::BatchRemoveCustomConfigurations()
} }
} }
pdlg->setLabelText(tr("%0/%1 custom configurations cleared").arg(removed).arg(total)); if (pdlg->wasCanceled())
pdlg->setCancelButtonText(tr("OK")); {
QApplication::beep(); pdlg->deleteLater(); // We did not allow deletion earlier to prevent segfaults when canceling.
game_list_log.notice("Custom Configuration Batch Removal was canceled. %d/%d custom configurations cleared", removed, total);
}
else
{
pdlg->SetDeleteOnClose();
pdlg->setLabelText(tr("%0/%1 custom configurations cleared").arg(removed).arg(total));
pdlg->setCancelButtonText(tr("OK"));
QApplication::beep();
}
Refresh(true); Refresh(true);
} }
@ -2153,7 +2171,7 @@ void game_list_frame::BatchRemoveCustomPadConfigurations()
return; return;
} }
progress_dialog* pdlg = new progress_dialog(tr("Custom Pad Configuration Batch Removal"), tr("Removing all custom pad configurations"), tr("Cancel"), 0, total, true, this); progress_dialog* pdlg = new progress_dialog(tr("Custom Pad Configuration Batch Removal"), tr("Removing all custom pad configurations"), tr("Cancel"), 0, total, false, this);
pdlg->setAutoClose(false); pdlg->setAutoClose(false);
pdlg->setAutoReset(false); pdlg->setAutoReset(false);
pdlg->show(); pdlg->show();
@ -2163,7 +2181,6 @@ void game_list_frame::BatchRemoveCustomPadConfigurations()
{ {
if (pdlg->wasCanceled()) if (pdlg->wasCanceled())
{ {
game_list_log.notice("Custom Pad Configuration Batch Removal was canceled. %d/%d custom pad configurations cleared", removed, total);
break; break;
} }
QApplication::processEvents(); QApplication::processEvents();
@ -2174,9 +2191,19 @@ void game_list_frame::BatchRemoveCustomPadConfigurations()
} }
} }
pdlg->setLabelText(tr("%0/%1 custom pad configurations cleared").arg(removed).arg(total)); if (pdlg->wasCanceled())
pdlg->setCancelButtonText(tr("OK")); {
QApplication::beep(); pdlg->deleteLater(); // We did not allow deletion earlier to prevent segfaults when canceling.
game_list_log.notice("Custom Pad Configuration Batch Removal was canceled. %d/%d custom pad configurations cleared", removed, total);
}
else
{
pdlg->SetDeleteOnClose();
pdlg->setLabelText(tr("%0/%1 custom pad configurations cleared").arg(removed).arg(total));
pdlg->setCancelButtonText(tr("OK"));
QApplication::beep();
}
Refresh(true); Refresh(true);
} }
@ -2200,7 +2227,7 @@ void game_list_frame::BatchRemoveShaderCaches()
return; return;
} }
progress_dialog* pdlg = new progress_dialog(tr("Shader Cache Batch Removal"), tr("Removing all shader caches"), tr("Cancel"), 0, total, true, this); progress_dialog* pdlg = new progress_dialog(tr("Shader Cache Batch Removal"), tr("Removing all shader caches"), tr("Cancel"), 0, total, false, this);
pdlg->setAutoClose(false); pdlg->setAutoClose(false);
pdlg->setAutoReset(false); pdlg->setAutoReset(false);
pdlg->show(); pdlg->show();
@ -2210,7 +2237,6 @@ void game_list_frame::BatchRemoveShaderCaches()
{ {
if (pdlg->wasCanceled()) if (pdlg->wasCanceled())
{ {
game_list_log.notice("Shader Cache Batch Removal was canceled");
break; break;
} }
QApplication::processEvents(); QApplication::processEvents();
@ -2221,9 +2247,18 @@ void game_list_frame::BatchRemoveShaderCaches()
} }
} }
pdlg->setLabelText(tr("%0/%1 shader caches cleared").arg(removed).arg(total)); if (pdlg->wasCanceled())
pdlg->setCancelButtonText(tr("OK")); {
QApplication::beep(); pdlg->deleteLater(); // We did not allow deletion earlier to prevent segfaults when canceling.
game_list_log.notice("Shader Cache Batch Removal was canceled");
}
else
{
pdlg->SetDeleteOnClose();
pdlg->setLabelText(tr("%0/%1 shader caches cleared").arg(removed).arg(total));
pdlg->setCancelButtonText(tr("OK"));
QApplication::beep();
}
} }
void game_list_frame::ShowCustomConfigIcon(const game_info& game) void game_list_frame::ShowCustomConfigIcon(const game_info& game)

View file

@ -13,7 +13,7 @@ progress_dialog::progress_dialog(const QString& windowTitle, const QString& labe
if (delete_on_close) if (delete_on_close)
{ {
connect(this, &QProgressDialog::canceled, this, &QProgressDialog::deleteLater); SetDeleteOnClose();
} }
// Try to find a window handle first // Try to find a window handle first
@ -49,6 +49,11 @@ void progress_dialog::SetValue(int progress)
QProgressDialog::setValue(value); QProgressDialog::setValue(value);
} }
void progress_dialog::SetDeleteOnClose()
{
connect(this, &QProgressDialog::canceled, this, &QProgressDialog::deleteLater);
}
void progress_dialog::SignalFailure() const void progress_dialog::SignalFailure() const
{ {
m_progress_indicator->signal_failure(); m_progress_indicator->signal_failure();

View file

@ -11,6 +11,7 @@ public:
~progress_dialog(); ~progress_dialog();
void SetRange(int min, int max); void SetRange(int min, int max);
void SetValue(int progress); void SetValue(int progress);
void SetDeleteOnClose();
void SignalFailure() const; void SignalFailure() const;
private: private: