From f20dd7565bb7bff3c5128d70a43fb1fbc63ff65a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 24 Sep 2026 11:22:18 -0600 Subject: [PATCH] Don't crash at exit with a download still in flight A request started since the last RequestManager::Update (headless never calls it) sat in newDownloads_, which CancelAll skipped. It was then destroyed along with the static g_DownloadManager at exit, and its destructor removed its progress bar from the already destroyed g_OSD: "mutex lock failed". Seen with a Netconf dialog still downloading the infra DNS json when a test ended. CancelAll now takes the new ones too, and runs at shutdown while g_OSD is still there. The Netconf json request is also let go of when the emulator shuts down, rather than living on into the next game. Co-Authored-By: Claude Opus 5.5 (1M context) --- Common/Net/HTTPRequest.cpp | 5 +++++ Core/HLE/sceNet.cpp | 6 ++++++ UI/NativeApp.cpp | 3 +++ headless/Headless.cpp | 4 ++++ 4 files changed, 18 insertions(+) diff --git a/Common/Net/HTTPRequest.cpp b/Common/Net/HTTPRequest.cpp index b41d18c093..6f260b099b 100644 --- a/Common/Net/HTTPRequest.cpp +++ b/Common/Net/HTTPRequest.cpp @@ -168,6 +168,11 @@ restart: } void RequestManager::CancelAll() { + // Including ones started since the last Update (headless never calls it). + for (auto &iter : newDownloads_) { + downloads_.push_back(iter); + } + newDownloads_.clear(); for (size_t i = 0; i < downloads_.size(); i++) { downloads_[i]->Cancel(); } diff --git a/Core/HLE/sceNet.cpp b/Core/HLE/sceNet.cpp index 290a8190e8..6005446bcd 100644 --- a/Core/HLE/sceNet.cpp +++ b/Core/HLE/sceNet.cpp @@ -660,6 +660,12 @@ void __NetApctlShutdown() { } void __NetShutdown() { + // A Netconf dialog may have started the json download. Don't leave it running past us. + if (g_infraDL) { + g_infraDL->Cancel(); + g_infraDL.reset(); + } + // Network Cleanup Net_Term(); diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index 1f4bdef0c7..420e3061a5 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -1862,6 +1862,9 @@ void NativeShutdown() { __UPnPShutdown(); + // A request finishing while globals are destroyed at exit touches g_OSD, which may be gone by then. + g_DownloadManager.CancelAll(); + net::Shutdown(); g_Discord.Shutdown(); diff --git a/headless/Headless.cpp b/headless/Headless.cpp index 2efcb855ea..e687ec7971 100644 --- a/headless/Headless.cpp +++ b/headless/Headless.cpp @@ -50,6 +50,7 @@ #include "Common/Thread/ThreadManager.h" #include "Common/GPU/Vulkan/VulkanGraphicsContext.h" #include "Core/CmdLine.h" +#include "Common/Net/HTTPRequest.h" #include "Core/Config.h" #include "Core/ConfigValues.h" #include "Core/Core.h" @@ -1185,6 +1186,9 @@ int main(int argc, const char* argv[]) { } #endif + // A request finishing while globals are destroyed at exit touches g_OSD, which may be gone by then. + g_DownloadManager.CancelAll(); + g_VFS.Clear(); g_logManager.Shutdown(); if (cmdLineOptions.DebuggerPort().has_value()) {