mirror of https://github.com/procxx/kepka.git
windows backtrace logging done, showing error when cant start telegram or previous launch was not finished properly
This commit is contained in:
parent
0f4405dbaf
commit
c8d7d23ee6
|
@ -271,26 +271,14 @@ void Application::singleInstanceChecked() {
|
|||
Global::start();
|
||||
|
||||
if (!Logs::started() || (!cManyInstance() && !Logs::instanceChecked())) {
|
||||
// show error window
|
||||
MessageBox(0, (QString::fromStdWString(L"Could not start Telegram Dekstop! Log:\n\n") + Logs::full()).toStdWString().c_str(), L"Error!", MB_ICONERROR);
|
||||
App::quit();
|
||||
new NotStartedWindow();
|
||||
} else {
|
||||
SignalHandlers::Status status = SignalHandlers::start();
|
||||
if (status == SignalHandlers::CantOpen) {
|
||||
// show error window
|
||||
MessageBox(0, (QString::fromStdWString(L"Could not start Telegram Dekstop! Log:\n\n") + Logs::full()).toStdWString().c_str(), L"Error!", MB_ICONERROR);
|
||||
App::quit();
|
||||
new NotStartedWindow();
|
||||
} else if (status == SignalHandlers::LastCrashed) {
|
||||
new LastCrashedWindow();
|
||||
} else {
|
||||
if (status == SignalHandlers::LastCrashed) {
|
||||
// show error window
|
||||
MessageBox(0, (QString::fromStdWString(L"Last time Telegram Dekstop crashed! Log:\n\n") + Logs::full()).toStdWString().c_str(), L"Error!", MB_ICONERROR);
|
||||
if (SignalHandlers::restart() == SignalHandlers::CantOpen) {
|
||||
// show error window
|
||||
MessageBox(0, (QString::fromStdWString(L"Could not start Telegram Dekstop! Log:\n\n") + Logs::full()).toStdWString().c_str(), L"Error!", MB_ICONERROR);
|
||||
App::quit();
|
||||
return;
|
||||
}
|
||||
}
|
||||
new AppClass();
|
||||
}
|
||||
}
|
||||
|
@ -1050,10 +1038,7 @@ void AppClass::execExternal(const QString &cmd) {
|
|||
}
|
||||
|
||||
AppClass::~AppClass() {
|
||||
abort();
|
||||
|
||||
_window.setParent(0);
|
||||
|
||||
anim::stopManager();
|
||||
|
||||
stopWebLoadManager();
|
||||
|
|
|
@ -4000,7 +4000,8 @@ HistoryDocument::HistoryDocument(const HistoryDocument &other) : HistoryFileMedi
|
|||
, _linkcancell(new DocumentCancelLink(_data))
|
||||
, _name(other._name)
|
||||
, _namew(other._namew)
|
||||
, _thumbw(other._thumbw) {
|
||||
, _thumbw(other._thumbw)
|
||||
, _caption(other._caption) {
|
||||
setLinks(new DocumentOpenLink(_data), new DocumentSaveLink(_data), new DocumentCancelLink(_data));
|
||||
|
||||
setStatusSize(other._statusSize);
|
||||
|
@ -4378,6 +4379,7 @@ HistoryGif::HistoryGif(const HistoryGif &other) : HistoryFileMedia()
|
|||
, _data(other._data)
|
||||
, _thumbw(other._thumbw)
|
||||
, _thumbh(other._thumbh)
|
||||
, _caption(other._caption)
|
||||
, _gif(0) {
|
||||
setLinks(new GifOpenLink(_data), new GifOpenLink(_data), new DocumentCancelLink(_data));
|
||||
|
||||
|
|
|
@ -551,6 +551,7 @@ namespace SignalHandlers {
|
|||
QByteArray CrashDumpPath;
|
||||
FILE *CrashDumpFile = 0;
|
||||
int CrashDumpFileNo = 0;
|
||||
char LaunchedDateTimeStr[32] = { 0 };
|
||||
|
||||
void _writeChar(char ch) {
|
||||
fwrite(&ch, 1, 1, CrashDumpFile);
|
||||
|
@ -569,26 +570,43 @@ namespace SignalHandlers {
|
|||
return stream;
|
||||
}
|
||||
|
||||
const dump &operator<<(const dump &stream, int num) {
|
||||
template <typename Type>
|
||||
const dump &_writeNumber(const dump &stream, Type number) {
|
||||
if (!CrashDumpFile) return stream;
|
||||
|
||||
if (num < 0) {
|
||||
if (number < 0) {
|
||||
_writeChar('-');
|
||||
num = -num;
|
||||
number = -number;
|
||||
}
|
||||
int upper = 1, prev = num / 10;
|
||||
Type upper = 1, prev = number / 10;
|
||||
while (prev >= upper) {
|
||||
upper *= 10;
|
||||
}
|
||||
while (upper > 0) {
|
||||
int digit = (num / upper);
|
||||
int digit = (number / upper);
|
||||
_writeChar('0' + digit);
|
||||
num -= digit * upper;
|
||||
number -= digit * upper;
|
||||
upper /= 10;
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
const dump &operator<<(const dump &stream, int num) {
|
||||
return _writeNumber(stream, num);
|
||||
}
|
||||
|
||||
const dump &operator<<(const dump &stream, DWORD num) {
|
||||
return _writeNumber(stream, num);
|
||||
}
|
||||
|
||||
const dump &operator<<(const dump &stream, DWORD64 num) {
|
||||
return _writeNumber(stream, num);
|
||||
}
|
||||
|
||||
Qt::HANDLE LoggingCrashThreadId = 0;
|
||||
bool LoggingCrashHeaderWritten = false;
|
||||
QMutex LoggingCrashMutex;
|
||||
|
||||
void Handler(int signum) {
|
||||
const char* name = 0;
|
||||
switch (signum) {
|
||||
|
@ -602,21 +620,48 @@ namespace SignalHandlers {
|
|||
#endif
|
||||
}
|
||||
|
||||
Qt::HANDLE thread = QThread::currentThreadId();
|
||||
if (thread == LoggingCrashThreadId) return;
|
||||
|
||||
QMutexLocker lock(&LoggingCrashMutex);
|
||||
LoggingCrashThreadId = thread;
|
||||
|
||||
if (!LoggingCrashHeaderWritten) {
|
||||
LoggingCrashHeaderWritten = true;
|
||||
if (cBetaVersion()) {
|
||||
dump() << "Version: " << cBetaVersion() << " beta\n";
|
||||
} else {
|
||||
dump() << "Version: " << AppVersion;
|
||||
if (cDevVersion()) {
|
||||
dump() << " dev\n";
|
||||
} else {
|
||||
dump() << "\n";
|
||||
}
|
||||
}
|
||||
dump() << "Launched: " << LaunchedDateTimeStr << "\n";
|
||||
dump() << "Platform: ";
|
||||
switch (cPlatform()) {
|
||||
case dbipWindows: dump() << "win"; break;
|
||||
case dbipMac: dump() << "mac"; break;
|
||||
case dbipMacOld: dump() << "macold"; break;
|
||||
case dbipLinux64: dump() << "linux64"; break;
|
||||
case dbipLinux32: dump() << "linux32"; break;
|
||||
}
|
||||
dump() << "\n";
|
||||
psWriteDump();
|
||||
dump() << "\n";
|
||||
}
|
||||
if (name) {
|
||||
dump() << "Caught signal " << signum << " (" << name << ")\n";
|
||||
dump() << "Caught signal " << signum << " (" << name << ") in thread " << uint64(thread) << "\n";
|
||||
} else {
|
||||
dump() << "Caught signal " << signum << "\n";
|
||||
dump() << "Caught signal " << signum << " in thread " << uint64(thread) << "\n";
|
||||
}
|
||||
dump() << "Platform: ";
|
||||
switch (cPlatform()) {
|
||||
case dbipWindows: dump() << "win"; break;
|
||||
case dbipMac: dump() << "mac"; break;
|
||||
case dbipMacOld: dump() << "macold"; break;
|
||||
case dbipLinux64: dump() << "linux64"; break;
|
||||
case dbipLinux32: dump() << "linux32"; break;
|
||||
}
|
||||
dump() << "\n\nBacktrace:\n";
|
||||
|
||||
dump() << "\nBacktrace:\n";
|
||||
psWriteStackTrace(CrashDumpFileNo);
|
||||
dump() << "\n";
|
||||
|
||||
LoggingCrashThreadId = 0;
|
||||
}
|
||||
|
||||
Status start() {
|
||||
|
@ -644,6 +689,10 @@ namespace SignalHandlers {
|
|||
if (CrashDumpFile) {
|
||||
CrashDumpFileNo = fileno(CrashDumpFile);
|
||||
|
||||
QByteArray launchedDateTime = QDateTime::currentDateTime().toString("dd.MM.yyyy hh:mm:ss").toUtf8();
|
||||
t_assert(launchedDateTime.size() < sizeof(LaunchedDateTimeStr));
|
||||
memcpy(LaunchedDateTimeStr, launchedDateTime.constData(), launchedDateTime.size());
|
||||
|
||||
signal(SIGABRT, SignalHandlers::Handler);
|
||||
signal(SIGSEGV, SignalHandlers::Handler);
|
||||
signal(SIGILL, SignalHandlers::Handler);
|
||||
|
|
|
@ -93,6 +93,8 @@ namespace SignalHandlers {
|
|||
};
|
||||
const dump &operator<<(const dump &stream, const char *str);
|
||||
const dump &operator<<(const dump &stream, int num);
|
||||
const dump &operator<<(const dump &stream, DWORD num);
|
||||
const dump &operator<<(const dump &stream, DWORD64 num);
|
||||
|
||||
enum Status {
|
||||
CantOpen,
|
||||
|
|
|
@ -37,6 +37,8 @@ int main(int argc, char *argv[]) {
|
|||
return psFixPrevious();
|
||||
} else if (cLaunchMode() == LaunchModeCleanup) {
|
||||
return psCleanup();
|
||||
} else if (cLaunchMode() == LaunchModeShowCrash) {
|
||||
return psShowCrash(QFileInfo(cStartUrl()).absoluteFilePath());
|
||||
}
|
||||
|
||||
Logs::Initializer _logs;
|
||||
|
|
|
@ -2368,52 +2368,76 @@ typedef BOOL (FAR STDAPICALLTYPE *t_miniDumpWriteDump)(
|
|||
);
|
||||
t_miniDumpWriteDump miniDumpWriteDump = 0;
|
||||
|
||||
//// SymCleanup()
|
||||
//typedef BOOL(__stdcall *tSC)(IN HANDLE hProcess);
|
||||
//tSC pSC;
|
||||
//
|
||||
// SymFunctionTableAccess64()
|
||||
typedef PVOID (FAR STDAPICALLTYPE *t_SymFunctionTableAccess64)(HANDLE hProcess, DWORD64 AddrBase);
|
||||
// Stack walk code is inspired by http://www.codeproject.com/Articles/11132/Walking-the-callstack
|
||||
|
||||
static const int StackEntryMaxNameLength = MAX_SYM_NAME + 1;
|
||||
|
||||
typedef BOOL(FAR STDAPICALLTYPE *t_SymCleanup)(
|
||||
_In_ HANDLE hProcess
|
||||
);
|
||||
t_SymCleanup symCleanup = 0;
|
||||
|
||||
typedef PVOID (FAR STDAPICALLTYPE *t_SymFunctionTableAccess64)(
|
||||
_In_ HANDLE hProcess,
|
||||
_In_ DWORD64 AddrBase
|
||||
);
|
||||
t_SymFunctionTableAccess64 symFunctionTableAccess64 = 0;
|
||||
|
||||
//// SymGetLineFromAddr64()
|
||||
//typedef BOOL(__stdcall *tSGLFA)(IN HANDLE hProcess, IN DWORD64 dwAddr,
|
||||
// OUT PDWORD pdwDisplacement, OUT PIMAGEHLP_LINE64 Line);
|
||||
//tSGLFA pSGLFA;
|
||||
//
|
||||
// SymGetModuleBase64()
|
||||
typedef DWORD64 (FAR STDAPICALLTYPE *t_SymGetModuleBase64)(IN HANDLE hProcess, IN DWORD64 dwAddr);
|
||||
typedef BOOL (FAR STDAPICALLTYPE *t_SymGetLineFromAddr64)(
|
||||
_In_ HANDLE hProcess,
|
||||
_In_ DWORD64 dwAddr,
|
||||
_Out_ PDWORD pdwDisplacement,
|
||||
_Out_ PIMAGEHLP_LINEW64 Line
|
||||
);
|
||||
t_SymGetLineFromAddr64 symGetLineFromAddr64 = 0;
|
||||
|
||||
typedef DWORD64 (FAR STDAPICALLTYPE *t_SymGetModuleBase64)(
|
||||
_In_ HANDLE hProcess,
|
||||
_In_ DWORD64 qwAddr
|
||||
);
|
||||
t_SymGetModuleBase64 symGetModuleBase64 = 0;
|
||||
|
||||
//// SymGetModuleInfo64()
|
||||
//typedef BOOL(__stdcall *tSGMI)(IN HANDLE hProcess, IN DWORD64 dwAddr, OUT IMAGEHLP_MODULE64_V2 *ModuleInfo);
|
||||
//tSGMI pSGMI;
|
||||
typedef BOOL (FAR STDAPICALLTYPE *t_SymGetModuleInfo64)(
|
||||
_In_ HANDLE hProcess,
|
||||
_In_ DWORD64 qwAddr,
|
||||
_Out_ PIMAGEHLP_MODULEW64 ModuleInfo
|
||||
);
|
||||
t_SymGetModuleInfo64 symGetModuleInfo64 = 0;
|
||||
|
||||
// // SymGetModuleInfo64()
|
||||
// typedef BOOL (__stdcall *tSGMI_V3)( IN HANDLE hProcess, IN DWORD64 dwAddr, OUT IMAGEHLP_MODULE64_V3 *ModuleInfo );
|
||||
// tSGMI_V3 pSGMI_V3;
|
||||
typedef DWORD (FAR STDAPICALLTYPE *t_SymGetOptions)(
|
||||
VOID
|
||||
);
|
||||
t_SymGetOptions symGetOptions = 0;
|
||||
|
||||
//// SymGetOptions()
|
||||
//typedef DWORD(__stdcall *tSGO)(VOID);
|
||||
//tSGO pSGO;
|
||||
//
|
||||
//// SymGetSymFromAddr64()
|
||||
//typedef BOOL(__stdcall *tSGSFA)(IN HANDLE hProcess, IN DWORD64 dwAddr,
|
||||
// OUT PDWORD64 pdwDisplacement, OUT PIMAGEHLP_SYMBOL64 Symbol);
|
||||
//tSGSFA pSGSFA;
|
||||
//
|
||||
//// SymInitialize()
|
||||
//typedef BOOL(__stdcall *tSI)(IN HANDLE hProcess, IN PSTR UserSearchPath, IN BOOL fInvadeProcess);
|
||||
//tSI pSI;
|
||||
//
|
||||
//// SymLoadModule64()
|
||||
//typedef DWORD64(__stdcall *tSLM)(IN HANDLE hProcess, IN HANDLE hFile,
|
||||
// IN PSTR ImageName, IN PSTR ModuleName, IN DWORD64 BaseOfDll, IN DWORD SizeOfDll);
|
||||
//tSLM pSLM;
|
||||
//
|
||||
//// SymSetOptions()
|
||||
//typedef DWORD(__stdcall *tSSO)(IN DWORD SymOptions);
|
||||
//tSSO pSSO;
|
||||
typedef DWORD (FAR STDAPICALLTYPE *t_SymSetOptions)(
|
||||
_In_ DWORD SymOptions
|
||||
);
|
||||
t_SymSetOptions symSetOptions = 0;
|
||||
|
||||
typedef BOOL (FAR STDAPICALLTYPE *t_SymGetSymFromAddr64)(
|
||||
IN HANDLE hProcess,
|
||||
IN DWORD64 dwAddr,
|
||||
OUT PDWORD64 pdwDisplacement,
|
||||
OUT PIMAGEHLP_SYMBOL64 Symbol
|
||||
);
|
||||
t_SymGetSymFromAddr64 symGetSymFromAddr64 = 0;
|
||||
|
||||
typedef BOOL (FAR STDAPICALLTYPE *t_SymInitialize)(
|
||||
_In_ HANDLE hProcess,
|
||||
_In_opt_ PCWSTR UserSearchPath,
|
||||
_In_ BOOL fInvadeProcess
|
||||
);
|
||||
t_SymInitialize symInitialize = 0;
|
||||
|
||||
typedef DWORD64 (FAR STDAPICALLTYPE *t_SymLoadModule64)(
|
||||
_In_ HANDLE hProcess,
|
||||
_In_opt_ HANDLE hFile,
|
||||
_In_opt_ PCSTR ImageName,
|
||||
_In_opt_ PCSTR ModuleName,
|
||||
_In_ DWORD64 BaseOfDll,
|
||||
_In_ DWORD SizeOfDll
|
||||
);
|
||||
t_SymLoadModule64 symLoadModule64;
|
||||
|
||||
typedef BOOL (FAR STDAPICALLTYPE *t_StackWalk64)(
|
||||
_In_ DWORD MachineType,
|
||||
|
@ -2428,13 +2452,20 @@ typedef BOOL (FAR STDAPICALLTYPE *t_StackWalk64)(
|
|||
);
|
||||
t_StackWalk64 stackWalk64 = 0;
|
||||
|
||||
//// UnDecorateSymbolName()
|
||||
//typedef DWORD(__stdcall WINAPI *tUDSN)(PCSTR DecoratedName, PSTR UnDecoratedName,
|
||||
// DWORD UndecoratedLength, DWORD Flags);
|
||||
//tUDSN pUDSN;
|
||||
//
|
||||
//typedef BOOL(__stdcall WINAPI *tSGSP)(HANDLE hProcess, PSTR SearchPath, DWORD SearchPathLength);
|
||||
//tSGSP pSGSP;
|
||||
typedef DWORD (FAR STDAPICALLTYPE *t_UnDecorateSymbolName)(
|
||||
PCSTR DecoratedName,
|
||||
PSTR UnDecoratedName,
|
||||
DWORD UndecoratedLength,
|
||||
DWORD Flags
|
||||
);
|
||||
t_UnDecorateSymbolName unDecorateSymbolName = 0;
|
||||
|
||||
typedef BOOL(FAR STDAPICALLTYPE *t_SymGetSearchPath)(
|
||||
_In_ HANDLE hProcess,
|
||||
_Out_writes_(SearchPathLength) PWSTR SearchPath,
|
||||
_In_ DWORD SearchPathLength
|
||||
);
|
||||
t_SymGetSearchPath symGetSearchPath = 0;
|
||||
|
||||
BOOL __stdcall ReadProcessMemoryRoutine64(
|
||||
_In_ HANDLE hProcess,
|
||||
|
@ -2442,11 +2473,11 @@ BOOL __stdcall ReadProcessMemoryRoutine64(
|
|||
_Out_writes_bytes_(nSize) PVOID lpBuffer,
|
||||
_In_ DWORD nSize,
|
||||
_Out_ LPDWORD lpNumberOfBytesRead
|
||||
) {
|
||||
) {
|
||||
SIZE_T st;
|
||||
BOOL bRet = ReadProcessMemory(hProcess, (LPVOID)qwBaseAddress, lpBuffer, nSize, &st);
|
||||
*lpNumberOfBytesRead = (DWORD)st;
|
||||
//printf("ReadMemory: hProcess: %p, baseAddr: %p, buffer: %p, size: %d, read: %d, result: %d\n", hProcess, (LPVOID) qwBaseAddress, lpBuffer, nSize, (DWORD) st, (DWORD) bRet);
|
||||
|
||||
return bRet;
|
||||
}
|
||||
|
||||
|
@ -2492,8 +2523,38 @@ HANDLE _generateDumpFileAtPath(const WCHAR *path) {
|
|||
return CreateFile(szFileName, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_WRITE|FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0);
|
||||
}
|
||||
|
||||
bool LoadDbgHelp() {
|
||||
if (miniDumpWriteDump) return true;
|
||||
// **************************************** ToolHelp32 ************************
|
||||
#define MAX_MODULE_NAME32 255
|
||||
#define TH32CS_SNAPMODULE 0x00000008
|
||||
#pragma pack( push, 8 )
|
||||
typedef struct tagMODULEENTRY32
|
||||
{
|
||||
DWORD dwSize;
|
||||
DWORD th32ModuleID; // This module
|
||||
DWORD th32ProcessID; // owning process
|
||||
DWORD GlblcntUsage; // Global usage count on the module
|
||||
DWORD ProccntUsage; // Module usage count in th32ProcessID's context
|
||||
BYTE * modBaseAddr; // Base address of module in th32ProcessID's context
|
||||
DWORD modBaseSize; // Size in bytes of module starting at modBaseAddr
|
||||
HMODULE hModule; // The hModule of this module in th32ProcessID's context
|
||||
char szModule[MAX_MODULE_NAME32 + 1];
|
||||
char szExePath[MAX_PATH];
|
||||
} MODULEENTRY32;
|
||||
typedef MODULEENTRY32 *PMODULEENTRY32;
|
||||
typedef MODULEENTRY32 *LPMODULEENTRY32;
|
||||
#pragma pack( pop )
|
||||
|
||||
typedef HANDLE (FAR STDAPICALLTYPE *t_CreateToolhelp32Snapshot)(DWORD dwFlags, DWORD th32ProcessID);
|
||||
t_CreateToolhelp32Snapshot createToolhelp32Snapshot = 0;
|
||||
|
||||
typedef BOOL (FAR STDAPICALLTYPE *t_Module32First)(HANDLE hSnapshot, LPMODULEENTRY32 lpme);
|
||||
t_Module32First module32First = 0;
|
||||
|
||||
typedef BOOL (FAR STDAPICALLTYPE *t_Module32Next)(HANDLE hSnapshot, LPMODULEENTRY32 lpme);
|
||||
t_Module32Next module32Next = 0;
|
||||
|
||||
bool LoadDbgHelp(bool extended = false) {
|
||||
if (miniDumpWriteDump && (!extended || symInitialize)) return true;
|
||||
|
||||
HMODULE hDll = 0;
|
||||
|
||||
|
@ -2526,52 +2587,158 @@ bool LoadDbgHelp() {
|
|||
|
||||
miniDumpWriteDump = (t_miniDumpWriteDump)GetProcAddress(hDll, "MiniDumpWriteDump");
|
||||
|
||||
//pSI = (tSI)GetProcAddress(m_hDbhHelp, "SymInitialize");
|
||||
//pSC = (tSC)GetProcAddress(m_hDbhHelp, "SymCleanup");
|
||||
|
||||
stackWalk64 = (t_StackWalk64)GetProcAddress(hDll, "StackWalk64");
|
||||
//pSGO = (tSGO)GetProcAddress(m_hDbhHelp, "SymGetOptions");
|
||||
//pSSO = (tSSO)GetProcAddress(m_hDbhHelp, "SymSetOptions");
|
||||
|
||||
symFunctionTableAccess64 = (t_SymFunctionTableAccess64)GetProcAddress(hDll, "SymFunctionTableAccess64");
|
||||
//pSGLFA = (tSGLFA)GetProcAddress(m_hDbhHelp, "SymGetLineFromAddr64");
|
||||
symGetModuleBase64 = (t_SymGetModuleBase64)GetProcAddress(hDll, "SymGetModuleBase64");
|
||||
//pSGMI = (tSGMI)GetProcAddress(m_hDbhHelp, "SymGetModuleInfo64");
|
||||
////pSGMI_V3 = (tSGMI_V3) GetProcAddress(m_hDbhHelp, "SymGetModuleInfo64" );
|
||||
//pSGSFA = (tSGSFA)GetProcAddress(m_hDbhHelp, "SymGetSymFromAddr64");
|
||||
//pUDSN = (tUDSN)GetProcAddress(m_hDbhHelp, "UnDecorateSymbolName");
|
||||
//pSLM = (tSLM)GetProcAddress(m_hDbhHelp, "SymLoadModule64");
|
||||
//pSGSP = (tSGSP)GetProcAddress(m_hDbhHelp, "SymGetSearchPath");
|
||||
|
||||
if (!miniDumpWriteDump ||
|
||||
!stackWalk64) {
|
||||
!stackWalk64 ||
|
||||
!symFunctionTableAccess64 ||
|
||||
!symGetModuleBase64) {
|
||||
miniDumpWriteDump = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
//// SymInitialize
|
||||
//if (szSymPath != NULL)
|
||||
// m_szSymPath = _strdup(szSymPath);
|
||||
//if (this->pSI(m_hProcess, m_szSymPath, FALSE) == FALSE)
|
||||
// this->m_parent->OnDbgHelpErr("SymInitialize", GetLastError(), 0);
|
||||
if (extended) {
|
||||
HANDLE hProcess = GetCurrentProcess();
|
||||
DWORD dwProcessId = GetCurrentProcessId();
|
||||
|
||||
//DWORD symOptions = this->pSGO(); // SymGetOptions
|
||||
//symOptions |= SYMOPT_LOAD_LINES;
|
||||
//symOptions |= SYMOPT_FAIL_CRITICAL_ERRORS;
|
||||
////symOptions |= SYMOPT_NO_PROMPTS;
|
||||
//// SymSetOptions
|
||||
//symOptions = this->pSSO(symOptions);
|
||||
symGetLineFromAddr64 = (t_SymGetLineFromAddr64)GetProcAddress(hDll, "SymGetLineFromAddrW64");
|
||||
symGetModuleInfo64 = (t_SymGetModuleInfo64)GetProcAddress(hDll, "SymGetModuleInfoW64");
|
||||
symGetSymFromAddr64 = (t_SymGetSymFromAddr64)GetProcAddress(hDll, "SymGetSymFromAddr64");
|
||||
unDecorateSymbolName = (t_UnDecorateSymbolName)GetProcAddress(hDll, "UnDecorateSymbolName");
|
||||
symInitialize = (t_SymInitialize)GetProcAddress(hDll, "SymInitializeW");
|
||||
symCleanup = (t_SymCleanup)GetProcAddress(hDll, "SymCleanup");
|
||||
symGetSearchPath = (t_SymGetSearchPath)GetProcAddress(hDll, "SymGetSearchPathW");
|
||||
symGetOptions = (t_SymGetOptions)GetProcAddress(hDll, "SymGetOptions");
|
||||
symSetOptions = (t_SymSetOptions)GetProcAddress(hDll, "SymSetOptions");
|
||||
symLoadModule64 = (t_SymLoadModule64)GetProcAddress(hDll, "SymLoadModule64");
|
||||
if (!symGetModuleInfo64 ||
|
||||
!symGetLineFromAddr64 ||
|
||||
!symGetSymFromAddr64 ||
|
||||
!unDecorateSymbolName ||
|
||||
!symInitialize ||
|
||||
!symCleanup ||
|
||||
!symGetOptions ||
|
||||
!symSetOptions ||
|
||||
!symLoadModule64) {
|
||||
symInitialize = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
//char buf[StackWalker::STACKWALK_MAX_NAMELEN] = { 0 };
|
||||
//if (this->pSGSP != NULL)
|
||||
//{
|
||||
// if (this->pSGSP(m_hProcess, buf, StackWalker::STACKWALK_MAX_NAMELEN) == FALSE)
|
||||
// this->m_parent->OnDbgHelpErr("SymGetSearchPath", GetLastError(), 0);
|
||||
//}
|
||||
//char szUserName[1024] = { 0 };
|
||||
//DWORD dwSize = 1024;
|
||||
//GetUserNameA(szUserName, &dwSize);
|
||||
//this->m_parent->OnSymInit(buf, symOptions, szUserName);
|
||||
const size_t nSymPathLen = 10 * MAX_PATH;
|
||||
WCHAR szSymPath[nSymPathLen] = { 0 };
|
||||
|
||||
wcscat_s(szSymPath, nSymPathLen, L".;..;");
|
||||
|
||||
WCHAR szTemp[MAX_PATH + 1] = { 0 };
|
||||
if (GetCurrentDirectory(MAX_PATH, szTemp) > 0) {
|
||||
wcscat_s(szSymPath, nSymPathLen, szTemp);
|
||||
wcscat_s(szSymPath, nSymPathLen, L";");
|
||||
}
|
||||
|
||||
if (GetModuleFileName(NULL, szTemp, MAX_PATH) > 0) {
|
||||
for (WCHAR *p = (szTemp + wcslen(szTemp) - 1); p >= szTemp; --p) {
|
||||
if ((*p == '\\') || (*p == '/') || (*p == ':')) {
|
||||
*p = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (wcslen(szTemp) > 0) {
|
||||
wcscat_s(szSymPath, nSymPathLen, szTemp);
|
||||
wcscat_s(szSymPath, nSymPathLen, L";");
|
||||
}
|
||||
}
|
||||
if (GetEnvironmentVariable(L"_NT_SYMBOL_PATH", szTemp, MAX_PATH) > 0) {
|
||||
wcscat_s(szSymPath, nSymPathLen, szTemp);
|
||||
wcscat_s(szSymPath, nSymPathLen, L";");
|
||||
}
|
||||
if (GetEnvironmentVariable(L"_NT_ALTERNATE_SYMBOL_PATH", szTemp, MAX_PATH) > 0) {
|
||||
wcscat_s(szSymPath, nSymPathLen, szTemp);
|
||||
wcscat_s(szSymPath, nSymPathLen, L";");
|
||||
}
|
||||
if (GetEnvironmentVariable(L"SYSTEMROOT", szTemp, MAX_PATH) > 0) {
|
||||
wcscat_s(szSymPath, nSymPathLen, szTemp);
|
||||
wcscat_s(szSymPath, nSymPathLen, L";");
|
||||
|
||||
// also add the "system32"-directory:
|
||||
wcscat_s(szTemp, MAX_PATH, L"\\system32");
|
||||
wcscat_s(szSymPath, nSymPathLen, szTemp);
|
||||
wcscat_s(szSymPath, nSymPathLen, L";");
|
||||
}
|
||||
|
||||
if (GetEnvironmentVariable(L"SYSTEMDRIVE", szTemp, MAX_PATH) > 0) {
|
||||
wcscat_s(szSymPath, nSymPathLen, L"SRV*");
|
||||
wcscat_s(szSymPath, nSymPathLen, szTemp);
|
||||
wcscat_s(szSymPath, nSymPathLen, L"\\websymbols*http://msdl.microsoft.com/download/symbols;");
|
||||
} else {
|
||||
wcscat_s(szSymPath, nSymPathLen, L"SRV*c:\\websymbols*http://msdl.microsoft.com/download/symbols;");
|
||||
}
|
||||
|
||||
if (symInitialize(hProcess, szSymPath, FALSE) == FALSE) {
|
||||
symInitialize = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
DWORD symOptions = symGetOptions();
|
||||
symOptions |= SYMOPT_LOAD_LINES;
|
||||
symOptions |= SYMOPT_FAIL_CRITICAL_ERRORS;
|
||||
symOptions = symSetOptions(symOptions);
|
||||
|
||||
//WCHAR buf[StackEntryMaxNameLength] = { 0 };
|
||||
//if (symGetSearchPath) {
|
||||
// if (symGetSearchPath(hProcess, buf, StackEntryMaxNameLength) == FALSE) {
|
||||
// return false;
|
||||
// }
|
||||
//}
|
||||
|
||||
//WCHAR szUserName[1024] = { 0 };
|
||||
//DWORD dwSize = 1024;
|
||||
//GetUserName(szUserName, &dwSize);
|
||||
|
||||
const WCHAR *dllname[] = { L"kernel32.dll", L"tlhelp32.dll" };
|
||||
HINSTANCE hToolhelp = NULL;
|
||||
|
||||
HANDLE hSnap;
|
||||
MODULEENTRY32 me;
|
||||
me.dwSize = sizeof(me);
|
||||
BOOL keepGoing;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < (sizeof(dllname) / sizeof(dllname[0])); i++) {
|
||||
hToolhelp = LoadLibrary(dllname[i]);
|
||||
if (!hToolhelp) continue;
|
||||
|
||||
createToolhelp32Snapshot = (t_CreateToolhelp32Snapshot)GetProcAddress(hToolhelp, "CreateToolhelp32Snapshot");
|
||||
module32First = (t_Module32First)GetProcAddress(hToolhelp, "Module32First");
|
||||
module32Next = (t_Module32Next)GetProcAddress(hToolhelp, "Module32Next");
|
||||
if (createToolhelp32Snapshot && module32First && module32Next) {
|
||||
break; // found the functions!
|
||||
}
|
||||
FreeLibrary(hToolhelp);
|
||||
hToolhelp = NULL;
|
||||
}
|
||||
|
||||
if (hToolhelp == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
hSnap = createToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessId);
|
||||
if (hSnap == (HANDLE)-1)
|
||||
return FALSE;
|
||||
|
||||
keepGoing = !!module32First(hSnap, &me);
|
||||
int cnt = 0;
|
||||
while (keepGoing) {
|
||||
symLoadModule64(hProcess, 0, me.szExePath, me.szModule, (DWORD64)me.modBaseAddr, me.modBaseSize);
|
||||
++cnt;
|
||||
keepGoing = !!module32Next(hSnap, &me);
|
||||
}
|
||||
CloseHandle(hSnap);
|
||||
FreeLibrary(hToolhelp);
|
||||
|
||||
return (cnt > 0);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -2627,8 +2794,6 @@ LPTOP_LEVEL_EXCEPTION_FILTER WINAPI RedirectedSetUnhandledExceptionFilter(_In_op
|
|||
return 0;
|
||||
}
|
||||
|
||||
// stack walking code taken from StackWalker
|
||||
static const int StackEntryMaxNameLength = 1024;
|
||||
struct StackEntry {
|
||||
DWORD64 offset; // if 0, we have no valid entry
|
||||
CHAR name[StackEntryMaxNameLength];
|
||||
|
@ -2637,12 +2802,12 @@ struct StackEntry {
|
|||
DWORD64 offsetFromSmybol;
|
||||
DWORD offsetFromLine;
|
||||
DWORD lineNumber;
|
||||
CHAR lineFileName[StackEntryMaxNameLength];
|
||||
WCHAR lineFileName[StackEntryMaxNameLength];
|
||||
DWORD symType;
|
||||
LPCSTR symTypeString;
|
||||
CHAR moduleName[StackEntryMaxNameLength];
|
||||
WCHAR moduleName[StackEntryMaxNameLength];
|
||||
DWORD64 baseOfImage;
|
||||
CHAR loadedImageName[StackEntryMaxNameLength];
|
||||
WCHAR loadedImageName[StackEntryMaxNameLength];
|
||||
};
|
||||
|
||||
enum StackEntryType {
|
||||
|
@ -2651,40 +2816,204 @@ enum StackEntryType {
|
|||
StackEntryLast,
|
||||
};
|
||||
|
||||
struct IMAGEHLP_MODULE64_V2 {
|
||||
DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_MODULE64)
|
||||
DWORD64 BaseOfImage; // base load address of module
|
||||
DWORD ImageSize; // virtual size of the loaded module
|
||||
DWORD TimeDateStamp; // date/time stamp from pe header
|
||||
DWORD CheckSum; // checksum from the pe header
|
||||
DWORD NumSyms; // number of symbols in the symbol table
|
||||
SYM_TYPE SymType; // type of symbols loaded
|
||||
CHAR ModuleName[32]; // module name
|
||||
CHAR ImageName[256]; // image name
|
||||
CHAR LoadedImageName[256]; // symbol file name
|
||||
};
|
||||
char GetModuleInfoData[2 * sizeof(IMAGEHLP_MODULEW64)];
|
||||
BOOL _getModuleInfo(HANDLE hProcess, DWORD64 baseAddr, IMAGEHLP_MODULEW64 *pModuleInfo) {
|
||||
pModuleInfo->SizeOfStruct = sizeof(IMAGEHLP_MODULEW64);
|
||||
|
||||
memcpy(GetModuleInfoData, pModuleInfo, sizeof(IMAGEHLP_MODULEW64));
|
||||
if (symGetModuleInfo64(hProcess, baseAddr, (IMAGEHLP_MODULEW64*)GetModuleInfoData) != FALSE) {
|
||||
// only copy as much memory as is reserved...
|
||||
memcpy(pModuleInfo, GetModuleInfoData, sizeof(IMAGEHLP_MODULEW64));
|
||||
pModuleInfo->SizeOfStruct = sizeof(IMAGEHLP_MODULEW64);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void psWriteDump() {
|
||||
OSVERSIONINFOEXA version;
|
||||
ZeroMemory(&version, sizeof(OSVERSIONINFOEXA));
|
||||
version.dwOSVersionInfoSize = sizeof(version);
|
||||
if (GetVersionExA((OSVERSIONINFOA*)&version) != FALSE) {
|
||||
SignalHandlers::dump() << "OS-Version: " << version.dwMajorVersion << "." << version.dwMinorVersion << "." << version.dwBuildNumber << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
char ImageHlpSymbol64[sizeof(IMAGEHLP_SYMBOL64) + StackEntryMaxNameLength];
|
||||
QString _showCrashDump(const QByteArray &crashdump) {
|
||||
HANDLE hProcess = GetCurrentProcess();
|
||||
|
||||
void psWriteStackTrace(int n) {
|
||||
if (!LoadDbgHelp()) return;
|
||||
QString initial = QString::fromUtf8(crashdump), result;
|
||||
QStringList lines = initial.split('\n');
|
||||
result.reserve(initial.size());
|
||||
int32 i = 0, l = lines.size();
|
||||
QString versionstr;
|
||||
uint64 version = 0, betaversion = 0;
|
||||
for (; i < l; ++i) {
|
||||
result.append(lines.at(i)).append('\n');
|
||||
QString line = lines.at(i).trimmed();
|
||||
if (line.startsWith(qstr("Version: "))) {
|
||||
versionstr = line.mid(qstr("Version: ").size()).trimmed();
|
||||
version = versionstr.toULongLong();
|
||||
if (versionstr.endsWith(qstr("beta"))) {
|
||||
if (version % 1000) {
|
||||
betaversion = version;
|
||||
} else {
|
||||
version /= 1000;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// maybe need to launch another executable
|
||||
QString tolaunch;
|
||||
if ((betaversion && betaversion != cBetaVersion()) || (!betaversion && version && version != AppVersion)) {
|
||||
QString path = cExeDir();
|
||||
QRegularExpressionMatch m = QRegularExpression("deploy/\\d+\\.\\d+/\\d+\\.\\d+\\.\\d+(/|\\.dev/|_\\d+/)(Telegram/)?$").match(path);
|
||||
if (m.hasMatch()) {
|
||||
QString base = path.mid(0, m.capturedStart()) + qstr("deploy/");
|
||||
int32 major = version / 1000000, minor = (version % 1000000) / 1000, micro = (version % 1000);
|
||||
base += qsl("%1.%2/%3.%4.%5").arg(major).arg(minor).arg(major).arg(minor).arg(micro);
|
||||
if (betaversion) {
|
||||
base += qsl("_%1").arg(betaversion);
|
||||
} else if (QDir(base + qstr(".dev")).exists()) {
|
||||
base += qstr(".dev");
|
||||
}
|
||||
if (QFile(base + qstr("/Telegram/Telegram.exe")).exists()) {
|
||||
base += qstr("/Telegram");
|
||||
}
|
||||
tolaunch = base + qstr("Telegram.exe");
|
||||
}
|
||||
}
|
||||
if (!tolaunch.isEmpty()) {
|
||||
if (QFile(tolaunch).exists()) {
|
||||
// run it
|
||||
return QString();
|
||||
} else {
|
||||
result.append(qsl("ERROR: executable '%1' for this crashdump was not found!").arg(tolaunch));
|
||||
}
|
||||
}
|
||||
|
||||
while (i < l) {
|
||||
for (; i < l; ++i) {
|
||||
result.append(lines.at(i)).append('\n');
|
||||
QString line = lines.at(i).trimmed();
|
||||
if (line == qstr("Backtrace:")) {
|
||||
++i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
IMAGEHLP_SYMBOL64 *pSym = NULL;
|
||||
IMAGEHLP_MODULEW64 Module;
|
||||
IMAGEHLP_LINEW64 Line;
|
||||
|
||||
pSym = (IMAGEHLP_SYMBOL64*)ImageHlpSymbol64;
|
||||
memset(pSym, 0, sizeof(IMAGEHLP_SYMBOL64) + StackEntryMaxNameLength);
|
||||
pSym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
|
||||
pSym->MaxNameLength = StackEntryMaxNameLength;
|
||||
|
||||
memset(&Line, 0, sizeof(Line));
|
||||
Line.SizeOfStruct = sizeof(Line);
|
||||
|
||||
memset(&Module, 0, sizeof(Module));
|
||||
Module.SizeOfStruct = sizeof(Module);
|
||||
|
||||
StackEntry csEntry;
|
||||
for (int32 start = i; i < l; ++i) {
|
||||
QString line = lines.at(i).trimmed();
|
||||
if (line.isEmpty()) break;
|
||||
|
||||
result.append(qsl("%1. ").arg(i + 1 - start));
|
||||
if (!QRegularExpression(qsl("^\\d+$")).match(line).hasMatch()) {
|
||||
if (!lines.at(i).startsWith(qstr("ERROR: "))) {
|
||||
result.append(qstr("BAD LINE: "));
|
||||
}
|
||||
result.append(line).append('\n');
|
||||
continue;
|
||||
}
|
||||
|
||||
DWORD64 address = line.toULongLong();
|
||||
|
||||
csEntry.offset = address;
|
||||
csEntry.name[0] = 0;
|
||||
csEntry.undName[0] = 0;
|
||||
csEntry.undFullName[0] = 0;
|
||||
csEntry.offsetFromSmybol = 0;
|
||||
csEntry.offsetFromLine = 0;
|
||||
csEntry.lineFileName[0] = 0;
|
||||
csEntry.lineNumber = 0;
|
||||
csEntry.loadedImageName[0] = 0;
|
||||
csEntry.moduleName[0] = 0;
|
||||
|
||||
if (symGetSymFromAddr64(hProcess, address, &(csEntry.offsetFromSmybol), pSym) != FALSE) {
|
||||
// TODO: Mache dies sicher...!
|
||||
strcpy_s(csEntry.name, pSym->Name);
|
||||
|
||||
unDecorateSymbolName(pSym->Name, csEntry.undName, StackEntryMaxNameLength, UNDNAME_NAME_ONLY);
|
||||
unDecorateSymbolName(pSym->Name, csEntry.undFullName, StackEntryMaxNameLength, UNDNAME_COMPLETE);
|
||||
|
||||
if (symGetLineFromAddr64) {
|
||||
if (symGetLineFromAddr64(hProcess, address, &(csEntry.offsetFromLine), &Line) != FALSE) {
|
||||
csEntry.lineNumber = Line.LineNumber;
|
||||
|
||||
// TODO: Mache dies sicher...!
|
||||
wcscpy_s(csEntry.lineFileName, Line.FileName);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result.append("ERROR: could not get Sym from Addr! for ").append(QString::number(address)).append('\n');
|
||||
continue;
|
||||
}
|
||||
|
||||
if (_getModuleInfo(hProcess, address, &Module) != FALSE) {
|
||||
// TODO: Mache dies sicher...!
|
||||
wcscpy_s(csEntry.moduleName, Module.ModuleName);
|
||||
}
|
||||
if (csEntry.name[0] == 0) {
|
||||
strcpy_s(csEntry.name, "(function-name not available)");
|
||||
}
|
||||
if (csEntry.undName[0] != 0) {
|
||||
strcpy_s(csEntry.name, csEntry.undName);
|
||||
}
|
||||
if (csEntry.undFullName[0] != 0) {
|
||||
strcpy_s(csEntry.name, csEntry.undFullName);
|
||||
}
|
||||
if (csEntry.lineFileName[0] == 0) {
|
||||
if (csEntry.moduleName[0] == 0) {
|
||||
wcscpy_s(csEntry.moduleName, L"module-name not available");
|
||||
}
|
||||
result.append(csEntry.name).append(qsl(" (%1) 0x%3").arg(QString::fromWCharArray(csEntry.moduleName)).arg(address, 0, 16)).append('\n');
|
||||
} else {
|
||||
QString file = QString::fromWCharArray(csEntry.lineFileName).toLower();
|
||||
int32 index = file.indexOf(qstr("tbuild\\tdesktop\\telegram\\"));
|
||||
if (index >= 0) {
|
||||
file = file.mid(index + qstr("tbuild\\tdesktop\\telegram\\").size());
|
||||
if (file.startsWith(qstr("sourcefiles\\"))) {
|
||||
file = file.mid(qstr("sourcefiles\\").size());
|
||||
}
|
||||
}
|
||||
result.append(csEntry.name).append(qsl(" (%1 - %2) 0x%3").arg(file).arg(csEntry.lineNumber).arg(address, 0, 16)).append('\n');
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void psWriteStackTrace(int file) {
|
||||
if (!LoadDbgHelp()) {
|
||||
SignalHandlers::dump() << "ERROR: Could not load dbghelp.dll!\n";
|
||||
return;
|
||||
}
|
||||
|
||||
HANDLE hThread = GetCurrentThread(), hProcess = GetCurrentProcess();
|
||||
const CONTEXT *context = NULL;
|
||||
LPVOID pUserData = NULL;
|
||||
|
||||
CONTEXT c;
|
||||
StackEntry csEntry;
|
||||
IMAGEHLP_SYMBOL64 *pSym = NULL;
|
||||
IMAGEHLP_MODULE64_V2 Module;
|
||||
IMAGEHLP_LINE64 Line;
|
||||
int frameNum;
|
||||
|
||||
if (!LoadDbgHelp()) {
|
||||
SignalHandlers::dump() << "ERROR: Could not load dbghelp.dll!\n";
|
||||
return;
|
||||
}
|
||||
|
||||
memset(&c, 0, sizeof(CONTEXT));
|
||||
c.ContextFlags = CONTEXT_FULL;
|
||||
RtlCaptureContext(&c);
|
||||
|
@ -2724,18 +3053,7 @@ void psWriteStackTrace(int n) {
|
|||
#error "Platform not supported!"
|
||||
#endif
|
||||
|
||||
pSym = (IMAGEHLP_SYMBOL64 *)ImageHlpSymbol64;
|
||||
memset(pSym, 0, sizeof(IMAGEHLP_SYMBOL64) + StackEntryMaxNameLength);
|
||||
pSym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
|
||||
pSym->MaxNameLength = StackEntryMaxNameLength;
|
||||
|
||||
memset(&Line, 0, sizeof(Line));
|
||||
Line.SizeOfStruct = sizeof(Line);
|
||||
|
||||
memset(&Module, 0, sizeof(Module));
|
||||
Module.SizeOfStruct = sizeof(Module);
|
||||
|
||||
for (frameNum = 0; ; ++frameNum) {
|
||||
for (frameNum = 0; frameNum < 1000; ++frameNum) {
|
||||
// get next stack frame (StackWalk64(), SymFunctionTableAccess64(), SymGetModuleBase64())
|
||||
// if this returns ERROR_INVALID_ADDRESS (487) or ERROR_NOACCESS (998), you can
|
||||
// assume that either you are done, or that the stack is so hosed that the next
|
||||
|
@ -2746,16 +3064,6 @@ void psWriteStackTrace(int n) {
|
|||
return;
|
||||
}
|
||||
|
||||
csEntry.offset = s.AddrPC.Offset;
|
||||
csEntry.name[0] = 0;
|
||||
csEntry.undName[0] = 0;
|
||||
csEntry.undFullName[0] = 0;
|
||||
csEntry.offsetFromSmybol = 0;
|
||||
csEntry.offsetFromLine = 0;
|
||||
csEntry.lineFileName[0] = 0;
|
||||
csEntry.lineNumber = 0;
|
||||
csEntry.loadedImageName[0] = 0;
|
||||
csEntry.moduleName[0] = 0;
|
||||
if (s.AddrPC.Offset == s.AddrReturn.Offset) {
|
||||
SignalHandlers::dump() << s.AddrPC.Offset << "\n";
|
||||
SignalHandlers::dump() << "ERROR: StackWalk64() endless callstack!";
|
||||
|
@ -2771,6 +3079,41 @@ void psWriteStackTrace(int n) {
|
|||
}
|
||||
}
|
||||
|
||||
int psShowCrash(const QString &crashdump) {
|
||||
QString text;
|
||||
|
||||
QFile dump(crashdump);
|
||||
if (dump.open(QIODevice::ReadOnly)) {
|
||||
text = qsl("Crash dump file '%1':\n\n").arg(QFileInfo(crashdump).absoluteFilePath());
|
||||
if (!LoadDbgHelp(true)) {
|
||||
text += qsl("ERROR: could not init dbghelp.dll!");
|
||||
} else {
|
||||
text += _showCrashDump(dump.readAll());
|
||||
symCleanup(GetCurrentProcess());
|
||||
}
|
||||
} else {
|
||||
text = qsl("ERROR: could not read crash dump file '%1'").arg(QFileInfo(crashdump).absoluteFilePath());
|
||||
}
|
||||
|
||||
WCHAR szTemp[MAX_PATH + 1] = { 0 };
|
||||
GetModuleFileName(NULL, szTemp, MAX_PATH);
|
||||
|
||||
QByteArray args[] = { QString::fromWCharArray(szTemp).toUtf8() };
|
||||
int a_argc = 1;
|
||||
char *a_argv[1] = { args[0].data() };
|
||||
QApplication app(a_argc, a_argv);
|
||||
|
||||
QTextEdit wnd;
|
||||
wnd.setReadOnly(true);
|
||||
wnd.setPlainText(text);
|
||||
|
||||
QRect scr(QApplication::primaryScreen()->availableGeometry());
|
||||
wnd.setGeometry(scr.x() + (scr.width() / 6), scr.y() + (scr.height() / 6), scr.width() / 2, scr.height() / 2);
|
||||
wnd.show();
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
|
||||
class StringReferenceWrapper {
|
||||
public:
|
||||
|
||||
|
|
|
@ -117,7 +117,9 @@ extern LPTOP_LEVEL_EXCEPTION_FILTER _oldWndExceptionFilter;
|
|||
LONG CALLBACK _exceptionFilter(EXCEPTION_POINTERS* pExceptionPointers);
|
||||
LPTOP_LEVEL_EXCEPTION_FILTER WINAPI RedirectedSetUnhandledExceptionFilter(_In_opt_ LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter);
|
||||
|
||||
void psWriteStackTrace(int n);
|
||||
void psWriteDump();
|
||||
void psWriteStackTrace(int file);
|
||||
int psShowCrash(const QString &crashdump);
|
||||
|
||||
void psDeleteDir(const QString &dir);
|
||||
|
||||
|
|
|
@ -215,6 +215,9 @@ void settingsParseArgs(int argc, char *argv[]) {
|
|||
gLaunchMode = LaunchModeFixPrevious;
|
||||
} else if (string("-cleanup") == argv[i]) {
|
||||
gLaunchMode = LaunchModeCleanup;
|
||||
} else if (string("-crash") == argv[i] && i + 1 < argc) {
|
||||
gLaunchMode = LaunchModeShowCrash;
|
||||
gStartUrl = fromUtf8Safe(argv[++i]);
|
||||
} else if (string("-noupdate") == argv[i]) {
|
||||
gNoStartUpdate = true;
|
||||
} else if (string("-tosettings") == argv[i]) {
|
||||
|
|
|
@ -87,6 +87,7 @@ enum LaunchMode {
|
|||
LaunchModeAutoStart,
|
||||
LaunchModeFixPrevious,
|
||||
LaunchModeCleanup,
|
||||
LaunchModeShowCrash,
|
||||
};
|
||||
DeclareReadSetting(LaunchMode, LaunchMode);
|
||||
DeclareSetting(QString, WorkingDir);
|
||||
|
|
|
@ -293,7 +293,7 @@ namespace ThirdParty {
|
|||
av_register_all();
|
||||
avcodec_register_all();
|
||||
|
||||
av_lockmgr_register(_ffmpegLockManager);
|
||||
// av_lockmgr_register(_ffmpegLockManager);
|
||||
|
||||
_sslInited = true;
|
||||
}
|
||||
|
|
|
@ -1825,3 +1825,62 @@ Window::~Window() {
|
|||
delete main;
|
||||
delete settings;
|
||||
}
|
||||
|
||||
NotStartedWindow::NotStartedWindow() : TWidget(0)
|
||||
, _label(this)
|
||||
, _log(this) {
|
||||
_label.setText(qsl("Could not start Telegram Desktop! Log:"));
|
||||
_label.show();
|
||||
|
||||
_log.setReadOnly(true);
|
||||
_log.setPlainText(Logs::full());
|
||||
_log.show();
|
||||
|
||||
QRect scr(QApplication::primaryScreen()->availableGeometry());
|
||||
setGeometry(scr.x() + (scr.width() / 6), scr.y() + (scr.height() / 6), scr.width() / 2, scr.height() / 2);
|
||||
show();
|
||||
}
|
||||
|
||||
void NotStartedWindow::closeEvent(QCloseEvent *e) {
|
||||
deleteLater();
|
||||
}
|
||||
|
||||
void NotStartedWindow::resizeEvent(QResizeEvent *e) {
|
||||
int padding = _label.sizeHint().height() / 2;
|
||||
_label.setGeometry(padding, padding, width() - 2 * padding, _label.sizeHint().height());
|
||||
_log.setGeometry(padding, padding * 2 + _label.sizeHint().height(), width() - 2 * padding, height() - 3 * padding - _label.sizeHint().height());
|
||||
}
|
||||
|
||||
LastCrashedWindow::LastCrashedWindow() : TWidget(0)
|
||||
, _label(this)
|
||||
, _log(this)
|
||||
, _send(this) {
|
||||
_label.setText(qsl("Could not start Telegram Desktop! Log:"));
|
||||
_label.show();
|
||||
|
||||
_log.setReadOnly(true);
|
||||
_log.setPlainText(Logs::full());
|
||||
_log.show();
|
||||
|
||||
_send.setText(qsl("Send Crash Report"));
|
||||
_send.show();
|
||||
|
||||
QRect scr(QApplication::primaryScreen()->availableGeometry());
|
||||
setGeometry(scr.x() + (scr.width() / 6), scr.y() + (scr.height() / 6), scr.width() / 2, scr.height() / 2);
|
||||
show();
|
||||
}
|
||||
|
||||
void LastCrashedWindow::closeEvent(QCloseEvent *e) {
|
||||
deleteLater();
|
||||
if (SignalHandlers::restart() == SignalHandlers::CantOpen) {
|
||||
new NotStartedWindow();
|
||||
} else {
|
||||
new AppClass();
|
||||
}
|
||||
}
|
||||
|
||||
void LastCrashedWindow::resizeEvent(QResizeEvent *e) {
|
||||
int padding = _label.sizeHint().height() / 2;
|
||||
_label.setGeometry(padding, padding, width() - 2 * padding, _label.sizeHint().height());
|
||||
_log.setGeometry(padding, padding * 2 + _label.sizeHint().height(), width() - 2 * padding, height() - 3 * padding - _label.sizeHint().height());
|
||||
}
|
||||
|
|
|
@ -169,7 +169,7 @@ public:
|
|||
|
||||
QRect clientRect() const;
|
||||
QRect photoRect() const;
|
||||
|
||||
|
||||
IntroWidget *introWidget();
|
||||
MainWidget *mainWidget();
|
||||
SettingsWidget *settingsWidget();
|
||||
|
@ -245,12 +245,12 @@ public slots:
|
|||
|
||||
void updateIsActive(int timeout = 0);
|
||||
void stateChanged(Qt::WindowState state);
|
||||
|
||||
|
||||
void checkHistoryActivation();
|
||||
void updateCounter();
|
||||
|
||||
void checkAutoLock();
|
||||
|
||||
|
||||
void showSettings();
|
||||
void hideSettings(bool fast = false);
|
||||
void layerHidden();
|
||||
|
@ -353,4 +353,39 @@ private:
|
|||
MediaView *_mediaView;
|
||||
};
|
||||
|
||||
class NotStartedWindow : public TWidget {
|
||||
public:
|
||||
|
||||
NotStartedWindow();
|
||||
|
||||
protected:
|
||||
|
||||
void closeEvent(QCloseEvent *e);
|
||||
void resizeEvent(QResizeEvent *e);
|
||||
|
||||
private:
|
||||
|
||||
QLabel _label;
|
||||
QTextEdit _log;
|
||||
|
||||
};
|
||||
|
||||
class LastCrashedWindow : public TWidget {
|
||||
public:
|
||||
|
||||
LastCrashedWindow();
|
||||
|
||||
protected:
|
||||
|
||||
void closeEvent(QCloseEvent *e);
|
||||
void resizeEvent(QResizeEvent *e);
|
||||
|
||||
private:
|
||||
|
||||
QLabel _label;
|
||||
QTextEdit _log;
|
||||
QPushButton _send;
|
||||
|
||||
};
|
||||
|
||||
#endif // MAINWINDOW_H
|
||||
|
|
Loading…
Reference in New Issue