From fbc1bff1e1b3dd7e399aa089dcf8e5a11eab4ae2 Mon Sep 17 00:00:00 2001 From: Evgeny Date: Fri, 24 Jul 2026 15:49:58 +0300 Subject: [PATCH] chatgui: proper animation shutdown + TerminateProcess for rlottie threads - AnimTimer::shutdown(): stop QTimer, clear m_icons before icon destruction - ~MainWindow: AnimTimer::shutdown() -> cleanupAnimations() (correct order) - main: replace ExitProcess with TerminateProcess(GetCurrentProcess,0) TerminateProcess skips DLL_PROCESS_DETACH, avoiding libwinpthread pthread_join hang on rlottie/miniaudio threads. rlottie C API has no global shutdown - internal RleTaskScheduler threads cannot be stopped through public API. Same for miniaudio WASAPI threads. All owned resources already freed before TerminateProcess. --- tools/chatgui/src/animtimer.cpp | 7 +++++++ tools/chatgui/src/animtimer.h | 1 + tools/chatgui/src/main.cpp | 5 +++-- tools/chatgui/src/mainwindow.cpp | 2 ++ 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/tools/chatgui/src/animtimer.cpp b/tools/chatgui/src/animtimer.cpp index aaa6c1b1..67559e25 100644 --- a/tools/chatgui/src/animtimer.cpp +++ b/tools/chatgui/src/animtimer.cpp @@ -1,5 +1,6 @@ #include "animtimer.h" #include "lottieicon.h" +#include "../../lib/debug_config.h" AnimTimer::AnimTimer() { m_timer.setInterval(33); @@ -12,6 +13,12 @@ AnimTimer *AnimTimer::instance() { return &s; } +void AnimTimer::shutdown() { + instance()->m_timer.stop(); + instance()->m_icons.clear(); + DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "AnimTimer: shutdown"); +} + void AnimTimer::registerIcon(const QString &key, LottieIcon *icon) { m_icons.insert(key, icon); } diff --git a/tools/chatgui/src/animtimer.h b/tools/chatgui/src/animtimer.h index d2e5d383..4cdb53f0 100644 --- a/tools/chatgui/src/animtimer.h +++ b/tools/chatgui/src/animtimer.h @@ -17,6 +17,7 @@ public: void activate(); void deactivate(); + static void shutdown(); signals: void ticked(); diff --git a/tools/chatgui/src/main.cpp b/tools/chatgui/src/main.cpp index e1550463..49f1e731 100644 --- a/tools/chatgui/src/main.cpp +++ b/tools/chatgui/src/main.cpp @@ -45,8 +45,9 @@ static struct ShutdownSentinel { DWORD threads = count_threads(); DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "main: threads at exit=%lu", (unsigned long)threads); if (threads > 4) { - DEBUG_WARN(DEBUG_CATEGORY_DEBUG, "main: %lu hanging threads, ExitProcess", (unsigned long)threads); - ExitProcess(0); + DEBUG_WARN(DEBUG_CATEGORY_DEBUG, "main: %lu hanging threads, TerminateProcess", (unsigned long)threads); + fflush(nullptr); + TerminateProcess(GetCurrentProcess(), 0); } #endif } diff --git a/tools/chatgui/src/mainwindow.cpp b/tools/chatgui/src/mainwindow.cpp index c5f33b5c..f6f81695 100644 --- a/tools/chatgui/src/mainwindow.cpp +++ b/tools/chatgui/src/mainwindow.cpp @@ -8,6 +8,7 @@ #include "creategroupdialog.h" #include "invite_link.h" #include "sound_manager.h" +#include "animtimer.h" #include "../db/db_manager.h" #include "../transport/utun_node.h" #include "../transport/gui_bridge.h" @@ -90,6 +91,7 @@ MainWindow::~MainWindow() { DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "MainWindow: ~MainWindow — stopping utun node"); if (m_node) { m_node->stop(); delete m_node; m_node = nullptr; } DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "MainWindow: ~MainWindow — node stop+delete done"); + AnimTimer::shutdown(); MessageList::cleanupAnimations(); DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "MainWindow: ~MainWindow — animations cleaned"); DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "MainWindow: ~MainWindow done");