From 9ffe07ff48fea2dd23169859247ae34d5804b8de Mon Sep 17 00:00:00 2001 From: Nico Meister Date: Sun, 18 Oct 2026 22:47:36 +0200 Subject: [PATCH] v2.9.4: Absturz beim Beenden behoben (Hintergrund-Threads, die noch auf den Server warten) Co-Authored-By: Claude Opus 5.5 --- source/admin.c | 8 +++++--- source/admin.h | 2 +- source/main.c | 17 ++++++++++++++--- source/update.c | 11 +++++++---- source/update.h | 3 ++- 5 files changed, 29 insertions(+), 12 deletions(-) diff --git a/source/admin.c b/source/admin.c index 5e0ec4c..a0c3e37 100644 --- a/source/admin.c +++ b/source/admin.c @@ -49,9 +49,11 @@ void admin_start(const char *server, u32 pid) bool admin_is(void) { return isAdmin; } -void admin_finish(void) +bool admin_finish(void) { - if (!thread) return; - if (R_SUCCEEDED(threadJoin(thread, 3ULL * 1000 * 1000 * 1000))) threadFree(thread); + if (!thread) return true; + if (R_FAILED(threadJoin(thread, 15ULL * 1000 * 1000 * 1000))) return false; // läuft noch + threadFree(thread); thread = NULL; + return true; } diff --git a/source/admin.h b/source/admin.h index f6fcff7..3e82637 100644 --- a/source/admin.h +++ b/source/admin.h @@ -6,4 +6,4 @@ void admin_start(const char *server, u32 pid); // Admin? (gemerkte Antwort, bis der Server geantwortet hat) bool admin_is(void); -void admin_finish(void); +bool admin_finish(void); // wartet höchstens 15 s, false = läuft noch diff --git a/source/main.c b/source/main.c index 8226879..e86875c 100644 --- a/source/main.c +++ b/source/main.c @@ -681,11 +681,22 @@ int main(int argc, char **argv) C3D_FrameEnd(0); } + // Hintergrund-Threads, die noch auf den Server warten, dürfen ihren Speicher nicht verlieren: Sonst + // schreiben sie nach dem Freigeben hinein und Luma zeigt einen Absturz (z. B. beim Neustart nach "Nintendo"). ftpctl_stop(NULL, 0); shopctl_exit(); - if (maintenanceThread) { threadJoin(maintenanceThread, U64_MAX); threadFree(maintenanceThread); } - admin_finish(); - update_finish(); + bool clean = true; + if (maintenanceThread) { + if (R_SUCCEEDED(threadJoin(maintenanceThread, 20ULL * 1000 * 1000 * 1000))) threadFree(maintenanceThread); + else clean = false; + } + clean = admin_finish() && clean; + clean = update_finish() && clean; + if (!clean) { + // Hart beenden, ohne Speicher freizugeben (der Kernel räumt alles auf) + aptExit(); + svcExitProcess(); + } frdswitch_exit(); nnid_exit(); httpcExit(); diff --git a/source/update.c b/source/update.c index e940586..3ce54ab 100644 --- a/source/update.c +++ b/source/update.c @@ -268,10 +268,13 @@ bool update_pending(void) return state == UPD_AVAILABLE || state == UPD_DOWNLOADING || state == UPD_INSTALLED; } -void update_finish(void) +bool update_finish(void) { - if (!thread) return; - // Läuft der Download noch, nicht freigeben: Die App beendet sich ohnehin. - if (R_SUCCEEDED(threadJoin(thread, 3ULL * 1000 * 1000 * 1000))) threadFree(thread); + if (!thread) return true; + // Läuft die Abfrage noch, nicht freigeben (sonst schreibt der Thread in freigegebenen Speicher). + // false = läuft noch, die App muss sich hart beenden (main.c). + if (R_FAILED(threadJoin(thread, 15ULL * 1000 * 1000 * 1000))) return false; + threadFree(thread); thread = NULL; + return true; } diff --git a/source/update.h b/source/update.h index ae04962..3c8db80 100644 --- a/source/update.h +++ b/source/update.h @@ -21,7 +21,8 @@ void update_download(void); bool update_pending(void); UpdateState update_state(void); const char *update_new_version(void); -void update_finish(void); +// Wartet auf den Hintergrund-Thread (höchstens 15 s). false = läuft noch. +bool update_finish(void); // Laufender Download-Versuch (1-3) int update_attempt(void); // Beschreibung des letzten Fehlers (Schritt und Code)