diff options
author | Andrey Lihatskiy <alihatskiy@productengine.com> | 2025-04-12 06:18:44 +0300 |
---|---|---|
committer | Andrey Lihatskiy <alihatskiy@productengine.com> | 2025-04-12 06:20:38 +0300 |
commit | cfad42bea9baa7390eed7422fca12e8c00833837 (patch) | |
tree | fb54cd667b9b31b1cb125c08a114a51b50fb4254 /indra/llwindow | |
parent | dab8b9c62300e897c9b3f5826cdc6419c64ee1a5 (diff) |
Refactor LLWindowWin32::LLWindowWin32Thread::wakeAndDestroy()
Key improvements:
1. Better error handling for thread detachment
2. More careful sequencing of operations
3. Ensuring the window is hidden before proceeding with other shutdown steps
4. Proper checking of thread joinability before detaching
Diffstat (limited to 'indra/llwindow')
-rw-r--r-- | indra/llwindow/llwindowwin32.cpp | 49 |
1 files changed, 35 insertions, 14 deletions
diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 3ef162a870..83ae302859 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -4846,41 +4846,62 @@ bool LLWindowWin32::LLWindowWin32Thread::wakeAndDestroy() { if (mQueue->isClosed()) { - LL_WARNS() << "Tried to close Queue. Win32 thread Queue already closed." <<LL_ENDL; + LL_WARNS() << "Tried to close Queue. Win32 thread Queue already closed." << LL_ENDL; return false; } - // Make sure we don't leave a blank toolbar button. - // Also hiding window now prevents user from suspending it - // via some action (like dragging it around) - ShowWindow(mWindowHandleThrd, SW_HIDE); - mGLReady = false; + // Hide the window immediately to prevent user interaction during shutdown + if (mWindowHandleThrd) + { + ShowWindow(mWindowHandleThrd, SW_HIDE); + } + + mGLReady = false; - // Schedule destruction + // Capture current handle before we lose it HWND old_handle = mWindowHandleThrd; - mDeleteOnExit = true; - SetWindowLongPtr(old_handle, GWLP_USERDATA, NULL); - // Let thread finish on its own and don't block main thread. - for (auto& pair : mThreads) + // Clear the user data to prevent callbacks from finding us + if (old_handle) { - pair.second.detach(); + SetWindowLongPtr(old_handle, GWLP_USERDATA, NULL); } + // Signal thread to clean up when done + mDeleteOnExit = true; + + // Close the queue first LL_DEBUGS("Window") << "Closing window's pool queue" << LL_ENDL; mQueue->close(); - // Post a nonsense user message to wake up the thread in - // case it is waiting for a getMessage() + // Wake up the thread if it's stuck in GetMessage() if (old_handle) { WPARAM wparam{ 0xB0B0 }; LL_DEBUGS("Window") << "PostMessage(" << std::hex << old_handle << ", " << WM_DUMMY_ << ", " << wparam << ")" << std::dec << LL_ENDL; + + // Use PostMessage to signal thread to wake up PostMessage(old_handle, WM_DUMMY_, wparam, 0x1337); } + // Cleanly detach threads instead of joining them to avoid blocking the main thread + // This is acceptable since the thread will self-delete with mDeleteOnExit + for (auto& pair : mThreads) + { + try { + // Only detach if the thread is joinable + if (pair.second.joinable()) + { + pair.second.detach(); + } + } + catch (const std::system_error& e) { + LL_WARNS("Window") << "Exception detaching thread: " << e.what() << LL_ENDL; + } + } + LL_DEBUGS("Window") << "thread pool shutdown complete" << LL_ENDL; return true; } |