- WINSCR: So after looking over all the logs from WCG and now from Jacob

Klein a pattern started to emerge.  At the end of the log files the last
        message logged was 0x12 which translates into WM_QUIT.  The latest
        documentation on WM_QUIT states it should never show up in the message
        loop to begin with.
        
        The docs now say that WM_QUIT should not be sent to the message loop by
        way of PostMessage.  We have been doing things this way for over 5 years.
        For all I know, this could have been carried over from the original screen
        saver sample application.
        
        Change the shutdown logic so that only the primary curtain window can call
        PostQuitMessage() and all other curtain windows just exit when they receive
        a WM_DESTROY message.
        
        I'm not sure what causes this to be a problem on some machines and not
        others.  But preliminary results from Jacob are encouraging.
        
    clientscr/
        screensaver_win.cpp, .h

svn path=/trunk/boinc/; revision=23294
This commit is contained in:
Rom Walton 2011-03-29 20:59:09 +00:00
parent f696d90893
commit d8b9b8b268
3 changed files with 222 additions and 35 deletions

View File

@ -1942,3 +1942,23 @@ Rom 29 Mar 2011
TermsOfUsePage.cpp
UserDisagreesPage.cpp, .h (Deleted)
WizardAttach.cpp, .h
Rom 29 Mar 2011
- WINSCR: So after looking over all the logs from WCG and now from Jacob
Klein a pattern started to emerge. At the end of the log files the last
message logged was 0x12 which translates into WM_QUIT. The latest
documentation on WM_QUIT states it should never show up in the message
loop to begin with.
The docs now say that WM_QUIT should not be sent to the message loop by
way of PostMessage. We have been doing things this way for over 5 years.
Change the shutdown logic so that only the primary curtain window can call
PostQuitMessage() and all other curtain windows just exit when they receive
a WM_DESTROY message.
I'm not sure what causes this to be a problem on some machines and not
others. But preliminary results from Jacob are encouraging.
clientscr/
screensaver_win.cpp, .h

View File

@ -825,7 +825,9 @@ BOOL CScreensaver::GetTextForError(
//
BOOL CScreensaver::CreateInputActivityThread() {
DWORD dwThreadID = 0;
BOINCTRACE(_T("CScreensaver::CreateInputActivityThread Start\n"));
m_hInputActivityThread = CreateThread(
NULL, // default security attributes
0, // use default stack size
@ -849,10 +851,13 @@ BOOL CScreensaver::CreateInputActivityThread() {
// Terminate the thread that is used to monitor input activity.
//
BOOL CScreensaver::DestroyInputActivityThread() {
BOINCTRACE(_T("CScreensaver::DestroyInputActivityThread: Shutting Down...\n"));
if (!TerminateThread(m_hInputActivityThread, 0)) {
BOINCTRACE(_T("CScreensaver::DestroyInputActivityThread: Failed to terminate input activity thread '%d'\n"), GetLastError());
return FALSE;
}
return TRUE;
}
@ -941,10 +946,13 @@ BOOL CScreensaver::CreateGraphicsWindowPromotionThread() {
// Terminate the thread that is used to promote the graphics window.
//
BOOL CScreensaver::DestroyGraphicsWindowPromotionThread() {
BOINCTRACE(_T("CScreensaver::DestroyGraphicsWindowPromotionThread: Shutting Down...\n"));
if (!TerminateThread(m_hGraphicsWindowPromotionThread, 0)) {
BOINCTRACE(_T("CScreensaver::DestroyGraphicsWindowPromotionThread: Failed to terminate graphics window promotion thread '%d'\n"), GetLastError());
return FALSE;
}
return TRUE;
}
@ -1036,7 +1044,9 @@ DWORD WINAPI CScreensaver::GraphicsWindowPromotionProc() {
//
BOOL CScreensaver::CreateDataManagementThread() {
DWORD dwThreadID = 0;
BOINCTRACE(_T("CScreensaver::CreateDataManagementThread Start\n"));
m_hDataManagementThread = CreateThread(
NULL, // default security attributes
0, // use default stack size
@ -1049,6 +1059,7 @@ BOOL CScreensaver::CreateDataManagementThread() {
BOINCTRACE(_T("CScreensaver::CreateDataManagementThread: Failed to create data management thread '%d'\n"), GetLastError());
return FALSE;
}
return TRUE;
}
@ -1058,15 +1069,23 @@ BOOL CScreensaver::CreateDataManagementThread() {
// Terminate the thread that is used to talk to the daemon.
//
BOOL CScreensaver::DestroyDataManagementThread() {
m_bQuitDataManagementProc = true; // Tell DataManagementProc thread to exit
for (int i = 0; i < 50; i++) { // Wait up to 5 second for DataManagementProc thread to exit
if (m_bDataManagementProcStopped) return true;
BOINCTRACE(_T("CScreensaver::DestoryDataManagementThread: Shutting down... \n"));
m_bQuitDataManagementProc = true;
for (int i = 0; i < 50; i++) {
if (m_bDataManagementProcStopped) {
BOINCTRACE(_T("CScreensaver::DestoryDataManagementThread: Thread gracefully shutdown \n"));
return TRUE;
}
boinc_sleep(0.1);
}
BOINCTRACE(_T("CScreensaver::DestoryDataManagementThread: Terminating thread... \n"));
if (!TerminateThread(m_hDataManagementThread, 0)) {
BOINCTRACE(_T("CScreensaver::DestoryDataManagementThread: Failed to terminate data management thread '%d'\n"), GetLastError());
BOINCTRACE(_T("CScreensaver::DestoryDataManagementThread: Failed to terminate thread '%d'\n"), GetLastError());
return FALSE;
}
return TRUE;
}
@ -1129,7 +1148,7 @@ HRESULT CScreensaver::CreateSaverWindow() {
cls2.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH);
cls2.hInstance = m_hInstance;
cls2.style = CS_VREDRAW|CS_HREDRAW;
cls2.lpfnWndProc = SaverProcStub;
cls2.lpfnWndProc = GenericSaverProcStub;
cls2.cbWndExtra = 0;
cls2.cbClsExtra = 0;
RegisterClass(&cls2);
@ -1243,21 +1262,21 @@ VOID CScreensaver::DoConfig() {
// Handle window messages for main screensaver windows.
// Handle window messages for main screensaver window.
//
LRESULT CScreensaver::SaverProc(
HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
) {
DWORD dwMonitor = 0;
#ifdef _DEBUG
for(DWORD iIndex = 0; iIndex < m_dwNumMonitors; iIndex++) {
if (hWnd == m_Monitors[iIndex].hWnd ) {
dwMonitor = iIndex;
}
}
#endif
BOINCTRACE(_T("CScreensaver::SaverProc [%d] hWnd '%d' uMsg '%X' wParam '%d' lParam '%d'\n"), dwMonitor, hWnd, uMsg, wParam, lParam);
#endif
switch (uMsg) {
case WM_TIMER:
@ -1322,7 +1341,7 @@ LRESULT CScreensaver::SaverProc(
m_dwSaverMouseMoveCount++;
if (m_dwSaverMouseMoveCount > 5) {
BOINCTRACE(_T("CScreensaver::SaverProc Received WM_MOUSEMOVE and time to InterruptSaver()\n"));
InterruptSaver();
FireInterruptSaverEvent();
}
}
}
@ -1335,18 +1354,21 @@ LRESULT CScreensaver::SaverProc(
case WM_MBUTTONDOWN:
BOINCTRACE(_T("CScreensaver::SaverProc Received WM_KEYDOWN | WM_LBUTTONDOWN | WM_RBUTTONDOWN | WM_MBUTTONDOWN\n"));
if (m_SaverMode != sm_test) {
InterruptSaver();
FireInterruptSaverEvent();
}
return 0;
break;
case WM_CLOSE:
case WM_DESTROY:
BOINCTRACE(_T("CScreensaver::SaverProc Received WM_CLOSE or WM_DESTROY\n"));
BOINCTRACE(_T("CScreensaver::SaverProc Received WM_CLOSE\n"));
if (m_SaverMode == sm_preview || m_SaverMode == sm_test) {
ShutdownSaver();
FireInterruptSaverEvent();
}
return 0;
break;
case WM_DESTROY:
BOINCTRACE(_T("CScreensaver::SaverProc Received WM_DESTROY\n"));
PostQuitMessage(0);
break;
case WM_SYSCOMMAND:
@ -1374,7 +1396,7 @@ LRESULT CScreensaver::SaverProc(
case WM_POWERBROADCAST:
BOINCTRACE(_T("CScreensaver::SaverProc Received WM_POWERBROADCAST\n"));
if (wParam == PBT_APMQUERYSUSPEND)
InterruptSaver();
FireInterruptSaverEvent();
break;
}
@ -1388,7 +1410,155 @@ LRESULT CScreensaver::SaverProc(
} else if (WM_INTERRUPTSAVER == uMsg) {
BOINCTRACE(_T("CScreensaver::SaverProc Received WM_INTERRUPTSAVER\n"));
InterruptSaver();
ShutdownSaver();
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
// Handle window messages for secondary screensaver windows.
//
LRESULT CScreensaver::GenericSaverProc(
HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
) {
DWORD dwMonitor = 0;
#ifdef _DEBUG
for(DWORD iIndex = 0; iIndex < m_dwNumMonitors; iIndex++) {
if (hWnd == m_Monitors[iIndex].hWnd ) {
dwMonitor = iIndex;
}
}
BOINCTRACE(_T("CScreensaver::GenericSaverProc [%d] hWnd '%d' uMsg '%X' wParam '%d' lParam '%d'\n"), dwMonitor, hWnd, uMsg, wParam, lParam);
#endif
switch (uMsg) {
case WM_TIMER:
BOINCTRACE(_T("CScreensaver::GenericSaverProc Received WM_TIMER\n"));
switch (wParam) {
case 1:
// Initial idle time is done, proceed with initialization.
m_bWaitForInputIdle = FALSE;
KillTimer(hWnd, 1);
return 0;
break;
case 2:
// Create a screen saver window on the primary display if
// the boinc client crashes
CreateSaverWindow();
// Update the position of the box every second so that it
// does not end up off the visible area of the screen.
UpdateErrorBox();
return 0;
break;
}
break;
case WM_PAINT:
{
BOOL bErrorMode;
HRESULT hrError;
TCHAR szError[400];
GetError(bErrorMode, hrError, szError, sizeof(szError)/sizeof(TCHAR));
// Show error message, if there is one
PAINTSTRUCT ps;
BeginPaint(hWnd, &ps);
// In preview mode, just fill
// the preview window with black, and the BOINC icon.
if (!bErrorMode && m_SaverMode == sm_preview) {
RECT rc;
GetClientRect(hWnd,&rc);
FillRect(ps.hdc, &rc, (HBRUSH)GetStockObject(BLACK_BRUSH));
DrawIcon(ps.hdc, (rc.right / 2) - 16, (rc.bottom / 2) - 16,
LoadIcon(m_hInstance, MAKEINTRESOURCE(IDI_MAIN_ICON)));
} else {
DoPaint(hWnd, ps.hdc, &ps);
}
EndPaint(hWnd, &ps);
}
return 0;
break;
case WM_MOUSEMOVE:
if (m_SaverMode != sm_test) {
static INT xPrev = -1;
static INT yPrev = -1;
INT xCur = LOWORD(lParam);
INT yCur = HIWORD(lParam);
if (xCur != xPrev || yCur != yPrev) {
xPrev = xCur;
yPrev = yCur;
m_dwSaverMouseMoveCount++;
if (m_dwSaverMouseMoveCount > 5) {
BOINCTRACE(_T("CScreensaver::GenericSaverProc Received WM_MOUSEMOVE and time to InterruptSaver()\n"));
FireInterruptSaverEvent();
}
}
}
return 0;
break;
case WM_KEYDOWN:
case WM_LBUTTONDOWN:
case WM_RBUTTONDOWN:
case WM_MBUTTONDOWN:
BOINCTRACE(_T("CScreensaver::GenericSaverProc Received WM_KEYDOWN | WM_LBUTTONDOWN | WM_RBUTTONDOWN | WM_MBUTTONDOWN\n"));
if (m_SaverMode != sm_test) {
FireInterruptSaverEvent();
}
return 0;
break;
case WM_CLOSE:
BOINCTRACE(_T("CScreensaver::GenericSaverProc Received WM_CLOSE\n"));
if (m_SaverMode == sm_preview || m_SaverMode == sm_test) {
FireInterruptSaverEvent();
}
break;
case WM_SYSCOMMAND:
BOINCTRACE(_T("CScreensaver::GenericSaverProc Received WM_SYSCOMMAND\n"));
if (m_SaverMode == sm_full) {
switch (wParam) {
case SC_NEXTWINDOW:
case SC_PREVWINDOW:
case SC_SCREENSAVE:
case SC_CLOSE:
return 0;
}
}
break;
case WM_SETCURSOR:
BOINCTRACE(_T("CScreensaver::GenericSaverProc Received WM_SETCURSOR\n"));
if (m_SaverMode == sm_full) {
// Hide cursor
SetCursor(NULL);
return TRUE;
}
break;
case WM_POWERBROADCAST:
BOINCTRACE(_T("CScreensaver::GenericSaverProc Received WM_POWERBROADCAST\n"));
if (wParam == PBT_APMQUERYSUSPEND)
FireInterruptSaverEvent();
break;
}
if (WM_SETTIMER == uMsg) {
BOINCTRACE(_T("CScreensaver::GenericSaverProc Received WM_SETTIMER\n"));
// All initialization messages have gone through. Allow
// 500ms of idle time, then proceed with initialization.
SetTimer(hWnd, 1, 500, NULL);
}
@ -1546,6 +1716,18 @@ LRESULT CALLBACK CScreensaver::SaverProcStub(
// This function forwards all window messages to GenericSaverProc, which has
// access to the "this" pointer.
//
LRESULT CALLBACK CScreensaver::GenericSaverProcStub(
HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
) {
return gspScreensaver->GenericSaverProc(hWnd, uMsg, wParam, lParam);
}
INT_PTR CALLBACK CScreensaver::ConfigureDialogProcStub(
HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam
) {
@ -1567,14 +1749,10 @@ VOID CScreensaver::ShutdownSaver() {
// Kill the currently executing graphics application
terminate_screensaver(m_hGraphicsApplication, &m_running_result);
// Post message to drop out of message loop
// This can be called from the data management thread, so specifically
// lookup and post to the primary window instead of calling PostQuitMessage
// since PostQuitMessage posts to the current threads message pump if it
// exists.
// Close all screensaver windows
for(DWORD iIndex = 0; iIndex < m_dwNumMonitors; iIndex++) {
if ( m_Monitors[iIndex].hWnd ) {
PostMessage(m_Monitors[iIndex].hWnd, WM_QUIT, NULL, NULL);
DestroyWindow(m_Monitors[iIndex].hWnd);
}
}
@ -1599,18 +1777,6 @@ VOID CScreensaver::FireInterruptSaverEvent() {
// A message was received (mouse move, keydown, etc.) that may mean
// the screen saver should shut down.
//
VOID CScreensaver::InterruptSaver() {
BOINCTRACE(_T("CScreensaver::InterruptSaver Function Begin\n"));
ShutdownSaver();
BOINCTRACE(_T("CScreensaver::InterruptSaver Function End\n"));
}
// Update the box that shows the error message
//
VOID CScreensaver::UpdateErrorBox() {

View File

@ -217,7 +217,6 @@ protected:
HRESULT CreateSaverWindow();
VOID UpdateErrorBox();
VOID FireInterruptSaverEvent();
VOID InterruptSaver();
VOID ShutdownSaver();
@ -225,6 +224,7 @@ protected:
HRESULT DoSaver();
VOID DoPaint( HWND hwnd, HDC hdc, LPPAINTSTRUCT lpps );
LRESULT SaverProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
LRESULT GenericSaverProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
DWORD ConvertSliderPositionToTime( DWORD dwPosition );
DWORD ConvertTimeToSliderPosition( DWORD dwMinutes );
@ -234,6 +234,7 @@ protected:
INT_PTR ConfigureDialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
static LRESULT CALLBACK SaverProcStub( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
static LRESULT CALLBACK GenericSaverProcStub( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
static INT_PTR CALLBACK ConfigureDialogProcStub( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
protected: