Skip to content

Commit 2194777

Browse files
committed
SL-18721 Window shutdown adjustments
On viewer shutdown 1. Instead of handling potential WM_* messages viewer is no longer equiped to handle drop window's pointer and expect only WM_DESTROY 2. Detach thread and let it do its own thing, thread will delete itself 3. Reverts commit 1161262 Reason for the change: window was closing too early (as son as "LLApp" status changes) without proper cleanup
1 parent 505ed20 commit 2194777

File tree

2 files changed

+37
-67
lines changed

2 files changed

+37
-67
lines changed

indra/llcommon/threadpool.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ namespace LL
5555
* ThreadPool listens for application shutdown messages on the "LLApp"
5656
* LLEventPump. Call close() to shut down this ThreadPool early.
5757
*/
58-
virtual void close();
58+
void close();
5959

6060
std::string getName() const { return mName; }
6161
size_t getWidth() const { return mThreads.size(); }

indra/llwindow/llwindowwin32.cpp

Lines changed: 36 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -351,10 +351,9 @@ struct LLWindowWin32::LLWindowWin32Thread : public LL::ThreadPool
351351
LLWindowWin32Thread();
352352

353353
void run() override;
354-
void close() override;
355354

356355
// closes queue, wakes thread, waits until thread closes
357-
void wakeAndDestroy();
356+
bool wakeAndDestroy();
358357

359358
void glReady()
360359
{
@@ -425,6 +424,7 @@ struct LLWindowWin32::LLWindowWin32Thread : public LL::ThreadPool
425424
// *HACK: Attempt to prevent startup crashes by deferring memory accounting
426425
// until after some graphics setup. See SL-20177. -Cosmic,2023-09-18
427426
bool mGLReady = false;
427+
bool mDeleteOnExit = false;
428428
// best guess at available video memory in MB
429429
std::atomic<U32> mAvailableVRAM;
430430

@@ -997,7 +997,11 @@ void LLWindowWin32::close()
997997
mhDC = NULL;
998998
mWindowHandle = NULL;
999999

1000-
mWindowThread->wakeAndDestroy();
1000+
if (mWindowThread->wakeAndDestroy())
1001+
{
1002+
// thread will delete itselfs once done
1003+
mWindowThread = NULL;
1004+
}
10011005
}
10021006

10031007
BOOL LLWindowWin32::isValid()
@@ -3104,10 +3108,17 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
31043108
break;
31053109
}
31063110
}
3107-
else
3111+
else // (NULL == window_imp)
31083112
{
3109-
// (NULL == window_imp)
3110-
LL_DEBUGS("Window") << "No window implementation to handle message with, message code: " << U32(u_msg) << LL_ENDL;
3113+
if (u_msg == WM_DESTROY)
3114+
{
3115+
PostQuitMessage(0); // Posts WM_QUIT with an exit code of 0
3116+
return 0;
3117+
}
3118+
else
3119+
{
3120+
LL_DEBUGS("Window") << "No window implementation to handle message with, message code: " << U32(u_msg) << LL_ENDL;
3121+
}
31113122
}
31123123

31133124
// pass unhandled messages down to Windows
@@ -4563,25 +4574,11 @@ U32 LLWindowWin32::getAvailableVRAMMegabytes()
45634574
#endif // LL_WINDOWS
45644575

45654576
inline LLWindowWin32::LLWindowWin32Thread::LLWindowWin32Thread()
4566-
: LL::ThreadPool("Window Thread", 1, MAX_QUEUE_SIZE, true /*should be false, temporary workaround for SL-18721*/)
4577+
: LL::ThreadPool("Window Thread", 1, MAX_QUEUE_SIZE, false)
45674578
{
45684579
LL::ThreadPool::start();
45694580
}
45704581

4571-
void LLWindowWin32::LLWindowWin32Thread::close()
4572-
{
4573-
if (!mQueue->isClosed())
4574-
{
4575-
LL_WARNS() << "Closing window thread without using destroy_window_handler" << LL_ENDL;
4576-
LL::ThreadPool::close();
4577-
4578-
// Workaround for SL-18721 in case window closes too early and abruptly
4579-
LLSplashScreen::show();
4580-
LLSplashScreen::update("..."); // will be updated later
4581-
}
4582-
}
4583-
4584-
45854582
/**
45864583
* LogChange is to log changes in status while trying to avoid spamming the
45874584
* log with repeated messages, especially in a tight loop. It refuses to log
@@ -4926,14 +4923,19 @@ void LLWindowWin32::LLWindowWin32Thread::run()
49264923
}
49274924

49284925
cleanupDX();
4926+
4927+
if (mDeleteOnExit)
4928+
{
4929+
delete this;
4930+
}
49294931
}
49304932

4931-
void LLWindowWin32::LLWindowWin32Thread::wakeAndDestroy()
4933+
bool LLWindowWin32::LLWindowWin32Thread::wakeAndDestroy()
49324934
{
49334935
if (mQueue->isClosed())
49344936
{
4935-
LL_WARNS() << "Tried to close Queue. Win32 thread Queue already closed." << LL_ENDL;
4936-
return;
4937+
LL_WARNS() << "Tried to close Queue. Win32 thread Queue already closed." <<LL_ENDL;
4938+
return false;
49374939
}
49384940

49394941
// Make sure we don't leave a blank toolbar button.
@@ -4972,6 +4974,15 @@ void LLWindowWin32::LLWindowWin32Thread::wakeAndDestroy()
49724974
mGLReady = false;
49734975
});
49744976

4977+
mDeleteOnExit = true;
4978+
SetWindowLongPtr(old_handle, GWLP_USERDATA, NULL);
4979+
4980+
// Let thread finish on its own and don't block main thread.
4981+
for (auto& pair : mThreads)
4982+
{
4983+
pair.second.detach();
4984+
}
4985+
49754986
LL_DEBUGS("Window") << "Closing window's pool queue" << LL_ENDL;
49764987
mQueue->close();
49774988

@@ -4986,49 +4997,8 @@ void LLWindowWin32::LLWindowWin32Thread::wakeAndDestroy()
49864997
PostMessage(old_handle, WM_DUMMY_, wparam, 0x1337);
49874998
}
49884999

4989-
// There are cases where window will refuse to close,
4990-
// can't wait forever on join, check state instead
4991-
LLTimer timeout;
4992-
timeout.setTimerExpirySec(2.0);
4993-
while (!getQueue().done() && !timeout.hasExpired() && mWindowHandleThrd)
4994-
{
4995-
ms_sleep(100);
4996-
}
4997-
4998-
if (getQueue().done() || mWindowHandleThrd == NULL)
4999-
{
5000-
// Window is closed, started closing or is cleaning up
5001-
// now wait for our single thread to die.
5002-
if (mWindowHandleThrd)
5003-
{
5004-
LL_INFOS("Window") << "Window is closing, waiting on pool's thread to join, time since post: " << timeout.getElapsedSeconds() << "s" << LL_ENDL;
5005-
}
5006-
else
5007-
{
5008-
LL_DEBUGS("Window") << "Waiting on pool's thread, time since post: " << timeout.getElapsedSeconds() << "s" << LL_ENDL;
5009-
}
5010-
for (auto& pair : mThreads)
5011-
{
5012-
pair.second.join();
5013-
}
5014-
}
5015-
else
5016-
{
5017-
// Something suspended window thread, can't afford to wait forever
5018-
// so kill thread instead
5019-
// Ex: This can happen if user starts dragging window arround (if it
5020-
// was visible) or a modal notification pops up
5021-
LL_WARNS("Window") << "Window is frozen, couldn't perform clean exit" << LL_ENDL;
5022-
5023-
for (auto& pair : mThreads)
5024-
{
5025-
// very unsafe
5026-
TerminateThread(pair.second.native_handle(), 0);
5027-
pair.second.detach();
5028-
cleanupDX();
5029-
}
5030-
}
50315000
LL_DEBUGS("Window") << "thread pool shutdown complete" << LL_ENDL;
5001+
return true;
50325002
}
50335003

50345004
void LLWindowWin32::post(const std::function<void()>& func)

0 commit comments

Comments
 (0)