summaryrefslogtreecommitdiff
path: root/indra/llwindow/llwindowwin32.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llwindow/llwindowwin32.cpp')
-rw-r--r--indra/llwindow/llwindowwin32.cpp151
1 files changed, 73 insertions, 78 deletions
diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp
index f349c4aea8..70bdb25415 100644
--- a/indra/llwindow/llwindowwin32.cpp
+++ b/indra/llwindow/llwindowwin32.cpp
@@ -345,8 +345,13 @@ struct LLWindowWin32::LLWindowWin32Thread : public LL::ThreadPool
void run() override;
void close() override;
- // closes queue, wakes thread, waits until thread closes
- void wakeAndDestroy();
+ // Detroys handles and window
+ // Either post to or call from window thread
+ void destroyWindow();
+
+ // Closes queue, wakes thread, waits until thread closes.
+ // Call from main thread
+ bool wakeAndDestroy();
void glReady()
{
@@ -404,6 +409,7 @@ struct LLWindowWin32::LLWindowWin32Thread : public LL::ThreadPool
bool mGLReady = false;
bool mGotGLBuffer = false;
bool mShuttingDown = false;
+ LLAtomicBool mDeleteOnExit = false;
};
@@ -847,6 +853,7 @@ LLWindowWin32::~LLWindowWin32()
}
delete mDragDrop;
+ mDragDrop = NULL;
delete [] mWindowTitle;
mWindowTitle = NULL;
@@ -858,6 +865,7 @@ LLWindowWin32::~LLWindowWin32()
mWindowClassName = NULL;
delete mWindowThread;
+ mWindowThread = NULL;
}
void LLWindowWin32::show()
@@ -976,7 +984,11 @@ void LLWindowWin32::close()
mhDC = NULL;
mWindowHandle = NULL;
- mWindowThread->wakeAndDestroy();
+ if (mWindowThread->wakeAndDestroy())
+ {
+ // thread will delete itselfs once done
+ mWindowThread = NULL;
+ }
}
bool LLWindowWin32::isValid()
@@ -3096,10 +3108,17 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
break;
}
}
- else
+ else // (NULL == window_imp)
{
- // (NULL == window_imp)
- LL_DEBUGS("Window") << "No window implementation to handle message with, message code: " << U32(u_msg) << LL_ENDL;
+ if (u_msg == WM_DESTROY)
+ {
+ PostQuitMessage(0); // Posts WM_QUIT with an exit code of 0
+ return 0;
+ }
+ else
+ {
+ LL_DEBUGS("Window") << "No window implementation to handle message with, message code: " << U32(u_msg) << LL_ENDL;
+ }
}
// pass unhandled messages down to Windows
@@ -4786,14 +4805,50 @@ void LLWindowWin32::LLWindowWin32Thread::run()
}
#endif
}
+
+ destroyWindow();
+
+ if (mDeleteOnExit)
+ {
+ delete this;
+ }
}
-void LLWindowWin32::LLWindowWin32Thread::wakeAndDestroy()
+void LLWindowWin32::LLWindowWin32Thread::destroyWindow()
+{
+ if (mWindowHandleThrd != NULL && IsWindow(mWindowHandleThrd))
+ {
+ if (mhDCThrd)
+ {
+ if (!ReleaseDC(mWindowHandleThrd, mhDCThrd))
+ {
+ LL_WARNS("Window") << "Release of ghDC failed!" << LL_ENDL;
+ }
+ mhDCThrd = NULL;
+ }
+
+ // This causes WM_DESTROY to be sent *immediately*
+ if (!destroy_window_handler(mWindowHandleThrd))
+ {
+ LL_WARNS("Window") << "Failed to destroy Window! " << std::hex << GetLastError() << LL_ENDL;
+ }
+ }
+ else
+ {
+ // Something killed the window while we were busy destroying gl or handle somehow got broken
+ LL_WARNS("Window") << "Failed to destroy Window, invalid handle!" << LL_ENDL;
+ }
+ mWindowHandleThrd = NULL;
+ mhDCThrd = NULL;
+ mGLReady = false;
+}
+
+bool LLWindowWin32::LLWindowWin32Thread::wakeAndDestroy()
{
if (mQueue->isClosed())
{
- LL_WARNS() << "Tried to close Queue. Win32 thread Queue already closed." << LL_ENDL;
- return;
+ LL_WARNS() << "Tried to close Queue. Win32 thread Queue already closed." <<LL_ENDL;
+ return false;
}
mShuttingDown = true;
@@ -4805,34 +4860,14 @@ void LLWindowWin32::LLWindowWin32Thread::wakeAndDestroy()
// Schedule destruction
HWND old_handle = mWindowHandleThrd;
- post([this]()
- {
- if (IsWindow(mWindowHandleThrd))
- {
- if (mhDCThrd)
- {
- if (!ReleaseDC(mWindowHandleThrd, mhDCThrd))
- {
- LL_WARNS("Window") << "Release of ghDC failed!" << LL_ENDL;
- }
- mhDCThrd = NULL;
- }
-
- // This causes WM_DESTROY to be sent *immediately*
- if (!destroy_window_handler(mWindowHandleThrd))
- {
- LL_WARNS("Window") << "Failed to destroy Window! " << std::hex << GetLastError() << LL_ENDL;
- }
- }
- else
- {
- // Something killed the window while we were busy destroying gl or handle somehow got broken
- LL_WARNS("Window") << "Failed to destroy Window, invalid handle!" << LL_ENDL;
- }
- mWindowHandleThrd = NULL;
- mhDCThrd = NULL;
- mGLReady = false;
- });
+ mDeleteOnExit = true;
+ SetWindowLongPtr(old_handle, GWLP_USERDATA, NULL);
+
+ // Let thread finish on its own and don't block main thread.
+ for (auto& pair : mThreads)
+ {
+ pair.second.detach();
+ }
LL_DEBUGS("Window") << "Closing window's pool queue" << LL_ENDL;
mQueue->close();
@@ -4848,48 +4883,8 @@ void LLWindowWin32::LLWindowWin32Thread::wakeAndDestroy()
PostMessage(old_handle, WM_DUMMY_, wparam, 0x1337);
}
- // There are cases where window will refuse to close,
- // can't wait forever on join, check state instead
- LLTimer timeout;
- timeout.setTimerExpirySec(2.0);
- while (!getQueue().done() && !timeout.hasExpired() && mWindowHandleThrd)
- {
- ms_sleep(100);
- }
-
- if (getQueue().done() || mWindowHandleThrd == NULL)
- {
- // Window is closed, started closing or is cleaning up
- // now wait for our single thread to die.
- if (mWindowHandleThrd)
- {
- LL_INFOS("Window") << "Window is closing, waiting on pool's thread to join, time since post: " << timeout.getElapsedSeconds() << "s" << LL_ENDL;
- }
- else
- {
- LL_DEBUGS("Window") << "Waiting on pool's thread, time since post: " << timeout.getElapsedSeconds() << "s" << LL_ENDL;
- }
- for (auto& pair : mThreads)
- {
- pair.second.join();
- }
- }
- else
- {
- // Something suspended window thread, can't afford to wait forever
- // so kill thread instead
- // Ex: This can happen if user starts dragging window arround (if it
- // was visible) or a modal notification pops up
- LL_WARNS("Window") << "Window is frozen, couldn't perform clean exit" << LL_ENDL;
-
- for (auto& pair : mThreads)
- {
- // very unsafe
- TerminateThread(pair.second.native_handle(), 0);
- pair.second.detach();
- }
- }
LL_DEBUGS("Window") << "thread pool shutdown complete" << LL_ENDL;
+ return true;
}
void LLWindowWin32::post(const std::function<void()>& func)