summaryrefslogtreecommitdiff
path: root/indra/llwindow
diff options
context:
space:
mode:
authorAndrey Lihatskiy <alihatskiy@productengine.com>2025-04-12 06:18:44 +0300
committerAndrey Lihatskiy <alihatskiy@productengine.com>2025-04-12 06:20:38 +0300
commitcfad42bea9baa7390eed7422fca12e8c00833837 (patch)
treefb54cd667b9b31b1cb125c08a114a51b50fb4254 /indra/llwindow
parentdab8b9c62300e897c9b3f5826cdc6419c64ee1a5 (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.cpp49
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;
}