From e721be645681b9a6c7f3b7eb86b69690ad7d7fab Mon Sep 17 00:00:00 2001 From: spx Date: Wed, 31 Aug 2011 11:06:35 +0000 Subject: [PATCH] Fixed deadlock issue when About dialog is opened. --- Library/Litestep.cpp | 98 +++++++++++++++++++++++++++++++++---------- Library/Litestep.h | 1 + Library/Rainmeter.cpp | 11 ++--- Library/Rainmeter.h | 1 - 4 files changed, 81 insertions(+), 30 deletions(-) diff --git a/Library/Litestep.cpp b/Library/Litestep.cpp index e6ca0140..38517452 100644 --- a/Library/Litestep.cpp +++ b/Library/Litestep.cpp @@ -54,6 +54,9 @@ FPVAREXPANSION fpVarExpansion = NULL; typedef BOOL (WINAPI *FPLSLOG)(int nLevel, LPCSTR pszModule, LPCSTR pszMessage); FPLSLOG fpLSLog = NULL; +static CRITICAL_SECTION g_CsLog = {0}; +static CRITICAL_SECTION g_CsLogDelay = {0}; + static int logFound = 0; void ResetLoggingFlag() @@ -63,23 +66,35 @@ void ResetLoggingFlag() void InitalizeLitestep() { - // Use lsapi's methods instead of the stubs - HINSTANCE h = CSystem::RmLoadLibrary(L"lsapi.dll"); - if (h != NULL) + InitializeCriticalSection(&g_CsLog); + InitializeCriticalSection(&g_CsLogDelay); + + if (!CRainmeter::GetDummyLitestep()) { - fpAddBangCommand = (FPADDBANGCOMMAND)GetProcAddress(h, "AddBangCommand"); - fpBitmapToRegion = (FPBITMAPTOREGION)GetProcAddress(h, "BitmapToRegion"); - fpGetLitestepWnd = (FPGETLITESTEPWND)GetProcAddress(h, "GetLitestepWnd"); - fpGetRCString = (FPGETRCSTRING)GetProcAddress(h, "GetRCString"); - //fpGetRCInt = (FPGETRCINT)GetProcAddress(h, "GetRCInt"); - fpLSExecute = (FPLSEXECUTE)GetProcAddress(h, "LSExecute"); - fpRemoveBangCommand = (FPREMOVEBANGCOMMAND)GetProcAddress(h, "RemoveBangCommand"); - //fpTransparentBltLS = (FPTRANSPARENTBLTLS)GetProcAddress(h, "TransparentBltLS"); - fpVarExpansion = (FPVAREXPANSION)GetProcAddress(h, "VarExpansion"); - fpLSLog = (FPLSLOG)GetProcAddress(h, "_LSLog@12"); + // Use lsapi's methods instead of the stubs + HINSTANCE h = CSystem::RmLoadLibrary(L"lsapi.dll"); + if (h != NULL) + { + fpAddBangCommand = (FPADDBANGCOMMAND)GetProcAddress(h, "AddBangCommand"); + fpBitmapToRegion = (FPBITMAPTOREGION)GetProcAddress(h, "BitmapToRegion"); + fpGetLitestepWnd = (FPGETLITESTEPWND)GetProcAddress(h, "GetLitestepWnd"); + fpGetRCString = (FPGETRCSTRING)GetProcAddress(h, "GetRCString"); + //fpGetRCInt = (FPGETRCINT)GetProcAddress(h, "GetRCInt"); + fpLSExecute = (FPLSEXECUTE)GetProcAddress(h, "LSExecute"); + fpRemoveBangCommand = (FPREMOVEBANGCOMMAND)GetProcAddress(h, "RemoveBangCommand"); + //fpTransparentBltLS = (FPTRANSPARENTBLTLS)GetProcAddress(h, "TransparentBltLS"); + fpVarExpansion = (FPVAREXPANSION)GetProcAddress(h, "VarExpansion"); + fpLSLog = (FPLSLOG)GetProcAddress(h, "_LSLog@12"); + } } } +void FinalizeLitestep() +{ + DeleteCriticalSection(&g_CsLog); + DeleteCriticalSection(&g_CsLogDelay); +} + BOOL AddBangCommand(LPCSTR command, BangCommand f) { // Use the lsapi.dll version of the method if possible @@ -528,14 +543,11 @@ std::wstring ConvertUTF8ToWide(LPCSTR str) return szWide; } -BOOL LogInternal(int nLevel, LPCTSTR pszModule, LPCTSTR pszMessage) +BOOL LogInternal(int nLevel, LPCTSTR pszModule, ULONGLONG elapsed, LPCTSTR pszMessage) { // Add timestamp - static ULONGLONG startTime = CSystem::GetTickCount64(); - ULONGLONG time = CSystem::GetTickCount64(); - WCHAR buffer[128]; - _snwprintf_s(buffer, _TRUNCATE, L"%02llu:%02llu:%02llu.%03llu", (time - startTime) / (1000 * 60* 60), ((time - startTime) / (1000 * 60)) % 60, ((time - startTime) / 1000) % 60, (time - startTime) % 1000); + _snwprintf_s(buffer, _TRUNCATE, L"%02llu:%02llu:%02llu.%03llu", elapsed / (1000 * 60 * 60), (elapsed / (1000 * 60)) % 60, (elapsed / 1000) % 60, elapsed % 1000); if (Rainmeter) { @@ -621,6 +633,7 @@ BOOL LogInternal(int nLevel, LPCTSTR pszModule, LPCTSTR pszMessage) } } } + return TRUE; } @@ -628,7 +641,50 @@ BOOL LSLog(int nLevel, LPCTSTR pszModule, LPCTSTR pszMessage) { if (nLevel != LOG_DEBUG || Rainmeter->GetDebug()) { - return LogInternal(nLevel, pszModule, pszMessage); + struct DELAYED_LOG_INFO + { + int level; + std::wstring module; + ULONGLONG elapsed; + std::wstring message; + }; + static std::list c_LogDelay; + + static ULONGLONG startTime = CSystem::GetTickCount64(); + ULONGLONG elapsed = CSystem::GetTickCount64() - startTime; + + if (TryEnterCriticalSection(&g_CsLog)) + { + // Log the queued messages first + EnterCriticalSection(&g_CsLogDelay); + + while (!c_LogDelay.empty()) + { + DELAYED_LOG_INFO& logInfo = c_LogDelay.front(); + LogInternal(logInfo.level, logInfo.module.c_str(), logInfo.elapsed, logInfo.message.c_str()); + + c_LogDelay.erase(c_LogDelay.begin()); + } + + LeaveCriticalSection(&g_CsLogDelay); + + // Log the message + BOOL ret = LogInternal(nLevel, pszModule, elapsed, pszMessage); + + LeaveCriticalSection(&g_CsLog); + + return ret; + } + else + { + // Queue the message + EnterCriticalSection(&g_CsLogDelay); + + DELAYED_LOG_INFO logInfo = {nLevel, pszModule, elapsed, pszMessage}; + c_LogDelay.push_back(logInfo); + + LeaveCriticalSection(&g_CsLogDelay); + } } return TRUE; @@ -636,7 +692,7 @@ BOOL LSLog(int nLevel, LPCTSTR pszModule, LPCTSTR pszMessage) void Log(int nLevel, const WCHAR* message) { - LogInternal(nLevel, L"Rainmeter", message); + LSLog(nLevel, L"Rainmeter", message); } void LogWithArgs(int nLevel, const WCHAR* format, ... ) @@ -658,7 +714,7 @@ void LogWithArgs(int nLevel, const WCHAR* format, ... ) _set_invalid_parameter_handler(oldHandler); - LogInternal(nLevel, L"Rainmeter", buffer); + LSLog(nLevel, L"Rainmeter", buffer); va_end(args); delete [] buffer; diff --git a/Library/Litestep.h b/Library/Litestep.h index ab35663b..4da466f0 100644 --- a/Library/Litestep.h +++ b/Library/Litestep.h @@ -34,6 +34,7 @@ typedef void (BangCommand)(HWND sender, LPCSTR args); // Call this if you want to use lsapi.dll's functions instead of stubs void InitalizeLitestep(); +void FinalizeLitestep(); // The stubs BOOL AddBangCommand(LPCSTR command, BangCommand f); diff --git a/Library/Rainmeter.cpp b/Library/Rainmeter.cpp index a8bfe0a6..5880960b 100644 --- a/Library/Rainmeter.cpp +++ b/Library/Rainmeter.cpp @@ -1732,13 +1732,10 @@ CRainmeter::CRainmeter() : m_DisableRDP(false), m_DisableDragging(false), m_Logging(false), - m_CsLogData(), m_CurrentParser(), m_Instance(), m_GDIplusToken() { - InitializeCriticalSection(&m_CsLogData); - CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); InitCommonControls(); @@ -1776,9 +1773,9 @@ CRainmeter::~CRainmeter() UpdateDesktopWorkArea(true); } - CoUninitialize(); + FinalizeLitestep(); - DeleteCriticalSection(&m_CsLogData); + CoUninitialize(); GdiplusShutdown(m_GDIplusToken); } @@ -1817,7 +1814,7 @@ int CRainmeter::Initialize(HWND Parent, HINSTANCE Instance, LPCSTR szPath) m_Path = tmpSzPath; - if (!c_DummyLitestep) InitalizeLitestep(); + InitalizeLitestep(); bool bDefaultIniLocation = false; @@ -4273,9 +4270,7 @@ void CRainmeter::AddAboutLogInfo(int level, LPCWSTR time, LPCWSTR message) { // TODO: Store items in vector - EnterCriticalSection(&m_CsLogData); CDialogAbout::AddLogItem(level, time, message); - LeaveCriticalSection(&m_CsLogData); } void CRainmeter::SetLogging(bool logging) diff --git a/Library/Rainmeter.h b/Library/Rainmeter.h index d6e17f4f..5bf8b235 100644 --- a/Library/Rainmeter.h +++ b/Library/Rainmeter.h @@ -328,7 +328,6 @@ private: bool m_Logging; std::list m_LogData; - CRITICAL_SECTION m_CsLogData; std::wstring m_ConfigEditor; std::wstring m_LogViewer;