backtrace output for win platform added, testing with abort() call in ~AppClass()

This commit is contained in:
John Preston 2016-01-21 14:58:58 +08:00
parent d672353ff9
commit 0f4405dbaf
11 changed files with 507 additions and 72 deletions

View File

@ -231,6 +231,8 @@ void Application::socketReading() {
}
void Application::socketError(QLocalSocket::LocalSocketError e) {
if (App::quiting()) return;
if (_secondInstance) {
LOG(("Could not write show command, error %1, quiting..").arg(e));
return App::quit();
@ -265,18 +267,33 @@ void Application::singleInstanceChecked() {
if (cManyInstance()) {
Logs::multipleInstances();
}
if ((!cManyInstance() && !Logs::instanceChecked()) || !Logs::started()) {
MessageBox(0, (QString::fromStdWString(L"Could not initialize logs!\n\n") + Logs::full()).toStdWString().c_str(), L"Error!", MB_ICONERROR);
// show error window
App::quit();
return;
}
Global::start();
// if crashed, show window and try to autoupdate
new AppClass();
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();
} 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();
} 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();
}
}
}
void Application::socketDisconnected() {
@ -638,8 +655,6 @@ AppClass::AppClass() : QObject()
, _uploader(0) {
AppObject = this;
installSignalHandlers();
ThirdParty::start();
Sandbox::start();
Local::start();
@ -1035,6 +1050,8 @@ void AppClass::execExternal(const QString &cmd) {
}
AppClass::~AppClass() {
abort();
_window.setParent(0);
anim::stopManager();

View File

@ -179,6 +179,8 @@ namespace Notify {
struct GlobalDataStruct {
QString LangSystemISO;
int32 LangSystem = languageDefault;
QByteArray LastCrashDump;
};
GlobalDataStruct *GlobalData = 0;
@ -278,6 +280,7 @@ Type &Ref##Name() { \
DefineGlobalReadOnly(QString, LangSystemISO);
DefineGlobalReadOnly(int32, LangSystem);
DefineGlobal(QByteArray, LastCrashDump);
}

View File

@ -111,6 +111,7 @@ namespace Global {
DeclareGlobalReadOnly(QString, LangSystemISO);
DeclareGlobalReadOnly(int32, LangSystem);
DeclareGlobal(QByteArray, LastCrashDump);
}

View File

@ -267,13 +267,11 @@ namespace Logs {
}
bool workingDirChosen = cBetaVersion();
QString moveOldDataFrom;
QString initialWorkingDir = QDir(cWorkingDir()).absolutePath() + '/', moveOldDataFrom;
if (cBetaVersion()) {
cSetDebug(true);
#if (defined Q_OS_MAC || defined Q_OS_LINUX)
} else {
QString wasDir = QDir(cWorkingDir()).absolutePath() + '/';
#ifdef _DEBUG
cForceWorkingDir(cExeDir());
#else
@ -284,7 +282,7 @@ namespace Logs {
workingDirChosen = true;
#if (defined Q_OS_LINUX && !defined _DEBUG) // fix first version
moveOldDataFrom = wasDir;
moveOldDataFrom = initialWorkingDir;
#endif
#endif
@ -303,17 +301,22 @@ namespace Logs {
cForceWorkingDir(QDir(cWorkingDir()).absolutePath() + '/');
QDir().setCurrent(cWorkingDir());
QDir().mkpath(cWorkingDir() + qstr("tdata"));
Global::WorkingDirReady();
LOG(("Launched version: %1, dev: %2, beta: %3, debug mode: %4, test dc: %5").arg(AppVersion).arg(Logs::b(cDevVersion())).arg(cBetaVersion()).arg(Logs::b(cDebug())).arg(Logs::b(cTestMode())));
LOG(("Executable dir: %1, name: %2").arg(cExeDir()).arg(cExeName()));
LOG(("Working dir: %1").arg(cWorkingDir()));
LOG(("Arguments: %1").arg(cArguments()));
if (!LogsData->openMain()) {
delete LogsData;
LogsData = 0;
}
LOG(("Launched version: %1, dev: %2, beta: %3, debug mode: %4, test dc: %5").arg(AppVersion).arg(Logs::b(cDevVersion())).arg(cBetaVersion()).arg(Logs::b(cDebug())).arg(Logs::b(cTestMode())));
LOG(("Executable dir: %1, name: %2").arg(cExeDir()).arg(cExeName()));
LOG(("Initial working dir: %1").arg(initialWorkingDir));
LOG(("Working dir: %1").arg(cWorkingDir()));
LOG(("Arguments: %1").arg(cArguments()));
if (!LogsData) {
LOG(("Could not open '%1' for writing log!").arg(_logsFilePath(LogDataMain, qsl("_startXX"))));
return;
}
@ -333,11 +336,12 @@ namespace Logs {
for (LogsInMemoryList::const_iterator i = list.cbegin(), e = list.cend(); i != e; ++i) {
if (i->first == LogDataMain) {
_logsWrite(i->first, i->second);
LOG(("First: %1, %2").arg(i->first).arg(i->second));
}
}
}
LOG(("Logs started."));
LOG(("Logs started"));
}
Initializer::~Initializer() {
@ -368,6 +372,8 @@ namespace Logs {
return false;
}
if (LogsInMemory) {
t_assert(LogsInMemory != DeletedLogsInMemory);
LogsInMemoryList list = *LogsInMemory;
@ -539,3 +545,126 @@ void _moveOldDataFiles(const QString &wasDir) {
}
}
}
namespace SignalHandlers {
QByteArray CrashDumpPath;
FILE *CrashDumpFile = 0;
int CrashDumpFileNo = 0;
void _writeChar(char ch) {
fwrite(&ch, 1, 1, CrashDumpFile);
}
dump::~dump() {
if (CrashDumpFile) {
fflush(CrashDumpFile);
}
}
const dump &operator<<(const dump &stream, const char *str) {
if (!CrashDumpFile) return stream;
fwrite(str, 1, strlen(str), CrashDumpFile);
return stream;
}
const dump &operator<<(const dump &stream, int num) {
if (!CrashDumpFile) return stream;
if (num < 0) {
_writeChar('-');
num = -num;
}
int upper = 1, prev = num / 10;
while (prev >= upper) {
upper *= 10;
}
while (upper > 0) {
int digit = (num / upper);
_writeChar('0' + digit);
num -= digit * upper;
upper /= 10;
}
return stream;
}
void Handler(int signum) {
const char* name = 0;
switch (signum) {
case SIGABRT: name = "SIGABRT"; break;
case SIGSEGV: name = "SIGSEGV"; break;
case SIGILL: name = "SIGILL"; break;
case SIGFPE: name = "SIGFPE"; break;
#ifndef Q_OS_WIN
case SIGBUS: name = "SIGBUS"; break;
case SIGSYS: name = "SIGSYS"; break;
#endif
}
if (name) {
dump() << "Caught signal " << signum << " (" << name << ")\n";
} else {
dump() << "Caught signal " << signum << "\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";
psWriteStackTrace(CrashDumpFileNo);
}
Status start() {
CrashDumpPath = (cWorkingDir() + qsl("tdata/working")).toUtf8();
if (FILE *f = fopen(CrashDumpPath.constData(), "rb")) {
QByteArray lastdump;
char buffer[64 * 1024] = { 0 };
int32 read = 0;
while ((read = fread(buffer, 1, 64 * 1024, f)) > 0) {
lastdump.append(buffer, read);
}
fclose(f);
Global::SetLastCrashDump(lastdump);
LOG(("Opened '%1' for reading, the previous Telegram Desktop launch was not finished properly :( Crash log size: %2").arg(QString::fromUtf8(CrashDumpPath)).arg(lastdump.size()));
return LastCrashed;
}
return restart();
}
Status restart() {
CrashDumpFile = fopen(CrashDumpPath.constData(), "wb");
if (CrashDumpFile) {
CrashDumpFileNo = fileno(CrashDumpFile);
signal(SIGABRT, SignalHandlers::Handler);
signal(SIGSEGV, SignalHandlers::Handler);
signal(SIGILL, SignalHandlers::Handler);
signal(SIGFPE, SignalHandlers::Handler);
#ifndef Q_OS_WIN
signal(SIGBUS, SignalHandlers::Handler);
signal(SIGSYS, SignalHandlers::Handler);
#endif
return Started;
}
LOG(("Could not open '%1' for writing!").arg(QString::fromUtf8(CrashDumpPath)));
return CantOpen;
}
void finish() {
if (CrashDumpFile) {
fclose(CrashDumpFile);
unlink(CrashDumpPath.constData());
}
}
}

View File

@ -85,3 +85,22 @@ namespace Logs {
#define MTP_LOG(dc, msg) { if (cDebug() || !Logs::started()) Logs::writeMtp(dc, QString msg); }
//usage MTP_LOG(dc, ("log: %1 %2").arg(1).arg(2))
namespace SignalHandlers {
struct dump {
~dump();
};
const dump &operator<<(const dump &stream, const char *str);
const dump &operator<<(const dump &stream, int num);
enum Status {
CantOpen,
LastCrashed,
Started
};
Status start();
Status restart(); // can be only CantOpen or Started
void finish();
}

View File

@ -67,5 +67,6 @@ int main(int argc, char *argv[]) {
psExecTelegram();
}
SignalHandlers::finish();
return result;
}

View File

@ -2368,6 +2368,88 @@ 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);
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);
t_SymGetModuleBase64 symGetModuleBase64 = 0;
//// SymGetModuleInfo64()
//typedef BOOL(__stdcall *tSGMI)(IN HANDLE hProcess, IN DWORD64 dwAddr, OUT IMAGEHLP_MODULE64_V2 *ModuleInfo);
//tSGMI pSGMI;
// // SymGetModuleInfo64()
// typedef BOOL (__stdcall *tSGMI_V3)( IN HANDLE hProcess, IN DWORD64 dwAddr, OUT IMAGEHLP_MODULE64_V3 *ModuleInfo );
// tSGMI_V3 pSGMI_V3;
//// 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 BOOL (FAR STDAPICALLTYPE *t_StackWalk64)(
_In_ DWORD MachineType,
_In_ HANDLE hProcess,
_In_ HANDLE hThread,
_Inout_ LPSTACKFRAME64 StackFrame,
_Inout_ PVOID ContextRecord,
_In_opt_ PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,
_In_opt_ PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,
_In_opt_ PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,
_In_opt_ PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress
);
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;
BOOL __stdcall ReadProcessMemoryRoutine64(
_In_ HANDLE hProcess,
_In_ DWORD64 qwBaseAddress,
_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;
}
HANDLE _generateDumpFileAtPath(const WCHAR *path) {
static const int maxFileLen = MAX_PATH * 10;
@ -2381,7 +2463,7 @@ HANDLE _generateDumpFileAtPath(const WCHAR *path) {
}
}
WCHAR szFileName[maxFileLen];
WCHAR szFileName[maxFileLen];
WCHAR szExeName[maxFileLen];
wcscpy_s(szExeName, _exeName);
@ -2410,14 +2492,94 @@ 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;
HMODULE hDll = 0;
WCHAR szTemp[4096];
if (GetModuleFileName(NULL, szTemp, 4096) > 0) {
wcscat(szTemp, L".local");
if (GetFileAttributes(szTemp) == INVALID_FILE_ATTRIBUTES) {
// ".local" file does not exist, so we can try to load the dbghelp.dll from the "Debugging Tools for Windows"
if (GetEnvironmentVariable(L"ProgramFiles", szTemp, 4096) > 0) {
wcscat(szTemp, L"\\Debugging Tools for Windows\\dbghelp.dll");
// now check if the file exists:
if (GetFileAttributes(szTemp) != INVALID_FILE_ATTRIBUTES) {
hDll = LoadLibrary(szTemp);
}
}
// Still not found? Then try to load the 64-Bit version:
if (!hDll && (GetEnvironmentVariable(L"ProgramFiles", szTemp, 4096) > 0)) {
wcscat(szTemp, L"\\Debugging Tools for Windows 64-Bit\\dbghelp.dll");
if (GetFileAttributes(szTemp) != INVALID_FILE_ATTRIBUTES) {
hDll = LoadLibrary(szTemp);
}
}
}
}
if (!hDll) {
hDll = LoadLibrary(L"DBGHELP.DLL");
}
if (!hDll) return false;
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) {
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);
//DWORD symOptions = this->pSGO(); // SymGetOptions
//symOptions |= SYMOPT_LOAD_LINES;
//symOptions |= SYMOPT_FAIL_CRITICAL_ERRORS;
////symOptions |= SYMOPT_NO_PROMPTS;
//// SymSetOptions
//symOptions = this->pSSO(symOptions);
//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);
return true;
}
void _generateDump(EXCEPTION_POINTERS* pExceptionPointers) {
static const int maxFileLen = MAX_PATH * 10;
HMODULE hDll = LoadLibrary(L"DBGHELP.DLL");
if (!hDll) return;
miniDumpWriteDump = (t_miniDumpWriteDump)GetProcAddress(hDll, "MiniDumpWriteDump");
if (!miniDumpWriteDump) return;
if (!LoadDbgHelp()) return;
HANDLE hDumpFile = 0;
@ -2465,6 +2627,150 @@ 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];
CHAR undName[StackEntryMaxNameLength];
CHAR undFullName[StackEntryMaxNameLength];
DWORD64 offsetFromSmybol;
DWORD offsetFromLine;
DWORD lineNumber;
CHAR lineFileName[StackEntryMaxNameLength];
DWORD symType;
LPCSTR symTypeString;
CHAR moduleName[StackEntryMaxNameLength];
DWORD64 baseOfImage;
CHAR loadedImageName[StackEntryMaxNameLength];
};
enum StackEntryType {
StackEntryFirst,
StackEntryNext,
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 ImageHlpSymbol64[sizeof(IMAGEHLP_SYMBOL64) + StackEntryMaxNameLength];
void psWriteStackTrace(int n) {
if (!LoadDbgHelp()) 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);
// init STACKFRAME for first call
STACKFRAME64 s; // in/out stackframe
memset(&s, 0, sizeof(s));
DWORD imageType;
#ifdef _M_IX86
// normally, call ImageNtHeader() and use machine info from PE header
imageType = IMAGE_FILE_MACHINE_I386;
s.AddrPC.Offset = c.Eip;
s.AddrPC.Mode = AddrModeFlat;
s.AddrFrame.Offset = c.Ebp;
s.AddrFrame.Mode = AddrModeFlat;
s.AddrStack.Offset = c.Esp;
s.AddrStack.Mode = AddrModeFlat;
#elif _M_X64
imageType = IMAGE_FILE_MACHINE_AMD64;
s.AddrPC.Offset = c.Rip;
s.AddrPC.Mode = AddrModeFlat;
s.AddrFrame.Offset = c.Rsp;
s.AddrFrame.Mode = AddrModeFlat;
s.AddrStack.Offset = c.Rsp;
s.AddrStack.Mode = AddrModeFlat;
#elif _M_IA64
imageType = IMAGE_FILE_MACHINE_IA64;
s.AddrPC.Offset = c.StIIP;
s.AddrPC.Mode = AddrModeFlat;
s.AddrFrame.Offset = c.IntSp;
s.AddrFrame.Mode = AddrModeFlat;
s.AddrBStore.Offset = c.RsBSP;
s.AddrBStore.Mode = AddrModeFlat;
s.AddrStack.Offset = c.IntSp;
s.AddrStack.Mode = AddrModeFlat;
#else
#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) {
// 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
// deeper frame could not be found.
// CONTEXT need not to be suplied if imageTyp is IMAGE_FILE_MACHINE_I386!
if (!stackWalk64(imageType, hProcess, hThread, &s, &c, ReadProcessMemoryRoutine64, symFunctionTableAccess64, symGetModuleBase64, NULL)) {
SignalHandlers::dump() << "ERROR: Call to StackWalk64() failed!\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!";
return;
}
if (s.AddrPC.Offset != 0) { // we seem to have a valid PC
SignalHandlers::dump() << s.AddrPC.Offset << "\n";
}
if (s.AddrReturn.Offset == 0) {
break;
}
}
}
class StringReferenceWrapper {
public:

View File

@ -117,6 +117,8 @@ 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 psDeleteDir(const QString &dir);
void psUserActionDone();

View File

@ -22,6 +22,8 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
#define PSAPI_VERSION 1 // fix WinXP
//#define Q_NO_TEMPLATE_FRIENDS // fix some compiler difference issues
#include <signal.h>
#include <openssl/bn.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>

View File

@ -22,8 +22,6 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
#include "application.h"
#include <signal.h>
uint64 _SharedMemoryLocation[4] = { 0x00, 0x01, 0x02, 0x03 };
#ifdef Q_OS_WIN
@ -309,47 +307,6 @@ namespace ThirdParty {
}
namespace {
FILE *_crashDump = 0;
int _crashDumpNo = 0;
}
void _signalHandler(int signum) {
const char* name = 0;
switch (signum) {
case SIGABRT: name = "SIGABRT"; break;
case SIGSEGV: name = "SIGSEGV"; break;
case SIGILL: name = "SIGILL"; break;
case SIGFPE: name = "SIGFPE"; break;
#ifndef Q_OS_WIN
case SIGBUS: name = "SIGBUS"; break;
case SIGSYS: name = "SIGSYS"; break;
#endif
}
LOG(("Caught signal %1").arg(name));
if (name)
fprintf(stdout, "Caught signal %d (%s)\n", signum, name);
else
fprintf(stdout, "Caught signal %d\n", signum);
//printStackTrace();
}
void installSignalHandlers() {
_crashDump = fopen((cWorkingDir() + qsl("tdata/working")).toUtf8().constData(), "wb");
if (_crashDump) _crashDumpNo = fileno(_crashDump);
signal(SIGABRT, _signalHandler);
signal(SIGSEGV, _signalHandler);
signal(SIGILL, _signalHandler);
signal(SIGFPE, _signalHandler);
#ifndef Q_OS_WIN
signal(SIGBUS, _signalHandler);
signal(SIGSYS, _signalHandler);
#endif
}
bool checkms() {
int64 unixms = (myunixtime() - _timeStart) * 1000LL + _msAddToUnixtime;
int64 ms = int64(getms(true));

View File

@ -143,8 +143,6 @@ inline void mylocaltime(struct tm * _Tm, const time_t * _Time) {
#endif
}
void installSignalHandlers();
namespace ThirdParty {
void start();