mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-01-07 11:57:55 +08:00
[FancyZones] Crash on launch: fix exception handler (#14609)
* fix stacktrace logging * init logger before exception handler * wchar check
This commit is contained in:
parent
8743c2329e
commit
bd0db76e31
@ -9,10 +9,7 @@
|
|||||||
#include "winapi_error.h"
|
#include "winapi_error.h"
|
||||||
#include "../logger/logger.h"
|
#include "../logger/logger.h"
|
||||||
|
|
||||||
static IMAGEHLP_SYMBOL64* pSymbol = (IMAGEHLP_SYMBOL64*)malloc(sizeof(IMAGEHLP_SYMBOL64) + MAX_PATH * sizeof(TCHAR));
|
|
||||||
static IMAGEHLP_LINE64 line;
|
|
||||||
static BOOLEAN processingException = FALSE;
|
static BOOLEAN processingException = FALSE;
|
||||||
static CHAR modulePath[MAX_PATH];
|
|
||||||
|
|
||||||
static inline const char* exceptionDescription(const DWORD& code)
|
static inline const char* exceptionDescription(const DWORD& code)
|
||||||
{
|
{
|
||||||
@ -64,15 +61,15 @@ static inline const char* exceptionDescription(const DWORD& code)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Returns the index of the last backslash in the file path */
|
/* Returns the index of the last backslash in the file path */
|
||||||
inline int GetFilenameStart(CHAR* path)
|
inline int GetFilenameStart(wchar_t* path)
|
||||||
{
|
{
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
int found = 0;
|
int found = 0;
|
||||||
if (path != NULL)
|
if (path != NULL)
|
||||||
{
|
{
|
||||||
while (path[pos] != '\0' && pos < MAX_PATH)
|
while (path[pos] != L'\0' && pos < MAX_PATH)
|
||||||
{
|
{
|
||||||
if (path[pos] == '\\')
|
if (path[pos] == L'\\')
|
||||||
{
|
{
|
||||||
found = pos + 1;
|
found = pos + 1;
|
||||||
}
|
}
|
||||||
@ -83,22 +80,73 @@ inline int GetFilenameStart(CHAR* path)
|
|||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void LogStackTrace()
|
inline std::wstring GetModuleName(HANDLE process, const STACKFRAME64& stack)
|
||||||
{
|
{
|
||||||
BOOL result;
|
static wchar_t modulePath[MAX_PATH]{};
|
||||||
HANDLE thread;
|
const size_t size = sizeof(modulePath);
|
||||||
HANDLE process;
|
memset(&modulePath[0], '\0', size);
|
||||||
CONTEXT context;
|
|
||||||
STACKFRAME64 stack;
|
DWORD64 moduleBase = SymGetModuleBase64(process, stack.AddrPC.Offset);
|
||||||
ULONG frame;
|
if (!moduleBase)
|
||||||
DWORD64 dw64Displacement;
|
{
|
||||||
DWORD dwDisplacement;
|
Logger::error(L"Failed to get a module. {}", get_last_error_or_default(GetLastError()));
|
||||||
|
return std::wstring();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!GetModuleFileNameW((HINSTANCE)moduleBase, modulePath, MAX_PATH))
|
||||||
|
{
|
||||||
|
Logger::error(L"Failed to get a module path. {}", get_last_error_or_default(GetLastError()));
|
||||||
|
return std::wstring();
|
||||||
|
}
|
||||||
|
|
||||||
|
const int start = GetFilenameStart(modulePath);
|
||||||
|
return std::wstring(modulePath, start);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::wstring GetName(HANDLE process, const STACKFRAME64& stack)
|
||||||
|
{
|
||||||
|
static IMAGEHLP_SYMBOL64* pSymbol = (IMAGEHLP_SYMBOL64*)malloc(sizeof(IMAGEHLP_SYMBOL64) + MAX_PATH * sizeof(TCHAR));
|
||||||
|
if (!pSymbol)
|
||||||
|
{
|
||||||
|
return std::wstring();
|
||||||
|
}
|
||||||
|
|
||||||
memset(&stack, 0, sizeof(STACKFRAME64));
|
|
||||||
memset(pSymbol, '\0', sizeof(*pSymbol) + MAX_PATH);
|
memset(pSymbol, '\0', sizeof(*pSymbol) + MAX_PATH);
|
||||||
memset(&modulePath[0], '\0', sizeof(modulePath));
|
pSymbol->MaxNameLength = MAX_PATH;
|
||||||
|
pSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
|
||||||
|
|
||||||
|
DWORD64 dw64Displacement = 0;
|
||||||
|
if (!SymGetSymFromAddr64(process, stack.AddrPC.Offset, &dw64Displacement, pSymbol))
|
||||||
|
{
|
||||||
|
Logger::error(L"Failed to get a symbol. {}", get_last_error_or_default(GetLastError()));
|
||||||
|
return std::wstring();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string str = pSymbol->Name;
|
||||||
|
return std::wstring(str.begin(), str.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::wstring GetLine(HANDLE process, const STACKFRAME64& stack)
|
||||||
|
{
|
||||||
|
static IMAGEHLP_LINE64 line{};
|
||||||
|
|
||||||
|
memset(&line, '\0', sizeof(IMAGEHLP_LINE64));
|
||||||
|
line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
|
||||||
line.LineNumber = 0;
|
line.LineNumber = 0;
|
||||||
|
|
||||||
|
DWORD dwDisplacement = 0;
|
||||||
|
if (!SymGetLineFromAddr64(process, stack.AddrPC.Offset, &dwDisplacement, &line))
|
||||||
|
{
|
||||||
|
return std::wstring();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string fileName(line.FileName);
|
||||||
|
return L"(" + std::wstring(fileName.begin(), fileName.end()) + L":" + std::to_wstring(line.LineNumber) + L")";
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void LogStackTrace()
|
||||||
|
{
|
||||||
|
CONTEXT context;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
RtlCaptureContext(&context);
|
RtlCaptureContext(&context);
|
||||||
@ -109,9 +157,11 @@ inline void LogStackTrace()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
process = GetCurrentProcess();
|
STACKFRAME64 stack;
|
||||||
thread = GetCurrentThread();
|
memset(&stack, 0, sizeof(STACKFRAME64));
|
||||||
dw64Displacement = 0;
|
|
||||||
|
HANDLE process = GetCurrentProcess();
|
||||||
|
HANDLE thread = GetCurrentThread();
|
||||||
stack.AddrPC.Offset = context.Rip;
|
stack.AddrPC.Offset = context.Rip;
|
||||||
stack.AddrPC.Mode = AddrModeFlat;
|
stack.AddrPC.Mode = AddrModeFlat;
|
||||||
stack.AddrStack.Offset = context.Rsp;
|
stack.AddrStack.Offset = context.Rsp;
|
||||||
@ -119,8 +169,9 @@ inline void LogStackTrace()
|
|||||||
stack.AddrFrame.Offset = context.Rbp;
|
stack.AddrFrame.Offset = context.Rbp;
|
||||||
stack.AddrFrame.Mode = AddrModeFlat;
|
stack.AddrFrame.Mode = AddrModeFlat;
|
||||||
|
|
||||||
std::stringstream ss;
|
BOOL result = false;
|
||||||
for (frame = 0;; frame++)
|
std::wstringstream ss;
|
||||||
|
for (;;)
|
||||||
{
|
{
|
||||||
result = StackWalk64(
|
result = StackWalk64(
|
||||||
IMAGE_FILE_MACHINE_AMD64,
|
IMAGE_FILE_MACHINE_AMD64,
|
||||||
@ -138,34 +189,10 @@ inline void LogStackTrace()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
pSymbol->MaxNameLength = MAX_PATH;
|
ss << GetModuleName(process, stack) << "!" << GetName(process, stack) << GetLine(process, stack) << std::endl;
|
||||||
pSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
|
|
||||||
|
|
||||||
if (!SymGetSymFromAddr64(process, stack.AddrPC.Offset, &dw64Displacement, pSymbol))
|
|
||||||
{
|
|
||||||
Logger::error(L"Failed to get a symbol. {}", get_last_error_or_default(GetLastError()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
line.LineNumber = 0;
|
Logger::error(L"STACK TRACE\r\n{}", ss.str());
|
||||||
SymGetLineFromAddr64(process, stack.AddrPC.Offset, &dwDisplacement, &line);
|
|
||||||
|
|
||||||
DWORD64 moduleBase = SymGetModuleBase64(process, stack.AddrPC.Offset);
|
|
||||||
if (moduleBase)
|
|
||||||
{
|
|
||||||
if (!GetModuleFileNameA((HINSTANCE)moduleBase, modulePath, MAX_PATH))
|
|
||||||
{
|
|
||||||
Logger::error(L"Failed to get a module path. {}", get_last_error_or_default(GetLastError()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Logger::error(L"Failed to get a module. {}", get_last_error_or_default(GetLastError()));
|
|
||||||
}
|
|
||||||
|
|
||||||
ss << std::string(modulePath).substr(GetFilenameStart(modulePath)) << "!" << pSymbol->Name << "(" << line.FileName << ":" << line.LineNumber << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger::error("STACK TRACE\r\n{}", ss.str());
|
|
||||||
Logger::flush();
|
Logger::flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -218,7 +245,6 @@ inline void InitSymbols()
|
|||||||
{
|
{
|
||||||
// Preload symbols so they will be available in case of out-of-memory exception
|
// Preload symbols so they will be available in case of out-of-memory exception
|
||||||
SymSetOptions(SYMOPT_LOAD_LINES | SYMOPT_UNDNAME);
|
SymSetOptions(SYMOPT_LOAD_LINES | SYMOPT_UNDNAME);
|
||||||
line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
|
|
||||||
HANDLE process = GetCurrentProcess();
|
HANDLE process = GetCurrentProcess();
|
||||||
if (!SymInitialize(process, NULL, TRUE))
|
if (!SymInitialize(process, NULL, TRUE))
|
||||||
{
|
{
|
||||||
|
@ -25,9 +25,8 @@ const std::wstring instanceMutexName = L"Local\\PowerToys_FancyZones_InstanceMut
|
|||||||
int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ PWSTR lpCmdLine, _In_ int nCmdShow)
|
int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ PWSTR lpCmdLine, _In_ int nCmdShow)
|
||||||
{
|
{
|
||||||
winrt::init_apartment();
|
winrt::init_apartment();
|
||||||
InitUnhandledExceptionHandler_x64();
|
|
||||||
|
|
||||||
LoggerHelpers::init_logger(moduleName, internalPath, LogSettings::fancyZonesLoggerName);
|
LoggerHelpers::init_logger(moduleName, internalPath, LogSettings::fancyZonesLoggerName);
|
||||||
|
InitUnhandledExceptionHandler_x64();
|
||||||
|
|
||||||
auto mutex = CreateMutex(nullptr, true, instanceMutexName.c_str());
|
auto mutex = CreateMutex(nullptr, true, instanceMutexName.c_str());
|
||||||
if (mutex == nullptr)
|
if (mutex == nullptr)
|
||||||
|
Loading…
Reference in New Issue
Block a user