started crash reporting for linux

This commit is contained in:
John Preston 2016-01-30 21:24:42 +03:00
parent 8eef239b45
commit 52c29bac5d
5 changed files with 154 additions and 30 deletions

View File

@ -324,7 +324,7 @@ bool update() {
int main(int argc, char *argv[]) {
bool needupdate = true, autostart = false, debug = false, tosettings = false, startintray = false, testmode = false;
char *key = 0;
char *key = 0, *crashreport = 0;
for (int i = 1; i < argc; ++i) {
if (equal(argv[i], "-noupdate")) {
needupdate = false;
@ -342,7 +342,9 @@ int main(int argc, char *argv[]) {
key = argv[i];
} else if (equal(argv[i], "-workpath") && ++i < argc) {
workDir = argv[i];
}
} else if (equal(argv[i], "-crashreport") && ++i < argc) {
crashreport = argv[i];
}
}
openLog();
@ -408,17 +410,20 @@ int main(int argc, char *argv[]) {
char *args[MaxArgsCount] = {0}, p_noupdate[] = "-noupdate", p_autostart[] = "-autostart", p_debug[] = "-debug", p_tosettings[] = "-tosettings", p_key[] = "-key", p_startintray[] = "-startintray", p_testmode[] = "-testmode";
int argIndex = 0;
args[argIndex++] = path;
args[argIndex++] = p_noupdate;
if (autostart) args[argIndex++] = p_autostart;
if (debug) args[argIndex++] = p_debug;
if (startintray) args[argIndex++] = p_startintray;
if (testmode) args[argIndex++] = p_testmode;
if (tosettings) args[argIndex++] = p_tosettings;
if (key) {
args[argIndex++] = p_key;
args[argIndex++] = key;
}
if (crashreport) {
args[argIndex++] = crashreport;
} else {
args[argIndex++] = p_noupdate;
if (autostart) args[argIndex++] = p_autostart;
if (debug) args[argIndex++] = p_debug;
if (startintray) args[argIndex++] = p_startintray;
if (testmode) args[argIndex++] = p_testmode;
if (tosettings) args[argIndex++] = p_tosettings;
if (key) {
args[argIndex++] = p_key;
args[argIndex++] = key;
}
}
pid_t pid = fork();
switch (pid) {
case -1: writeLog("fork() failed!"); return 1;

View File

@ -973,6 +973,112 @@ QAbstractNativeEventFilter *psNativeEventFilter() {
return _psEventFilter;
}
void psWriteDump() {
}
void psWriteStackTrace(int file) {
void *addresses[1024] = { 0 };
size_t size = backtrace(addresses, 1024);
backtrace_symbols_fd(addresses, size, file);
}
QString demanglestr(const QString &mangled) {
QByteArray cmd = ("c++filt -n " + mangled).toUtf8();
FILE *f = popen(cmd.constData(), "r");
if (!f) return "BAD_SYMBOL_" + mangled;
QString result;
char buffer[4096] = { 0 };
while (!feof(f)) {
if (fgets(buffer, 4096, f) != NULL) {
result += buffer;
}
}
pclose(f);
return result.trimmed();
}
QString _showCrashDump(const QByteArray &crashdump, QString dumpfile) {
QString initial = QString::fromUtf8(crashdump), result;
QStringList lines = initial.split('\n');
result.reserve(initial.size());
int32 i = 0, l = lines.size();
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;
}
}
for (int32 start = i; i < l; ++i) {
QString line = lines.at(i).trimmed();
if (line.isEmpty()) break;
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;
}
QStringList lst = line.split(' ', QString::SkipEmptyParts);
result.append(lst.at(0)).append(' ');
for (int j = 1, s = lst.size();;) {
if (lst.at(j).startsWith('_')) {
result.append(demanglestr(lst.at(j)));
if (++j < s) {
result.append(' ');
for (;;) {
result.append(lst.at(j));
if (++j < s) {
result.append(' ');
} else {
break;
}
}
}
break;
} else if (j > 2) {
result.append(lst.at(j));
}
if (++j < s) {
result.append(' ');
} else {
break;
}
}
result.append('\n');
}
}
return result;
}
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());
text += _showCrashDump(dump.readAll(), crashdump);
} else {
text = qsl("ERROR: could not read crash dump file '%1'").arg(QFileInfo(crashdump).absoluteFilePath());
}
QByteArray args[] = { "" };
int a_argc = 1;
char *a_argv[1] = { args[0].data() };
QApplication app(a_argc, a_argv);
ShowCrashReportWindow wnd(text);
return app.exec();
}
bool _removeDirectory(const QString &path) { // from http://stackoverflow.com/questions/2256945/removing-a-non-empty-directory-programmatically-in-c-or-c
QByteArray pathRaw = QFile::encodeName(path);
DIR *d = opendir(pathRaw.constData());
@ -1243,15 +1349,15 @@ void psNewVersion() {
psRegisterCustomScheme();
}
bool _execUpdater(bool update = true) {
bool _execUpdater(bool update = true, const QString &crashreport = QString()) {
static const int MaxLen = 65536, MaxArgsCount = 128;
char path[MaxLen] = {0};
QByteArray data(QFile::encodeName(cExeDir() + "Updater"));
memcpy(path, data.constData(), data.size());
char *args[MaxArgsCount] = {0}, p_noupdate[] = "-noupdate", p_autostart[] = "-autostart", p_debug[] = "-debug", p_tosettings[] = "-tosettings", p_key[] = "-key", p_path[] = "-workpath", p_startintray[] = "-startintray", p_testmode[] = "-testmode";
char p_datafile[MaxLen] = {0}, p_pathbuf[MaxLen] = {0};
char *args[MaxArgsCount] = {0}, p_noupdate[] = "-noupdate", p_autostart[] = "-autostart", p_debug[] = "-debug", p_tosettings[] = "-tosettings", p_key[] = "-key", p_path[] = "-workpath", p_startintray[] = "-startintray", p_testmode[] = "-testmode", p_crashreport[] = "-crashreport";
char p_datafile[MaxLen] = {0}, p_pathbuf[MaxLen] = {0}, p_crashreportbuf[MaxLen] = {0};
int argIndex = 0;
args[argIndex++] = path;
if (!update) {
@ -1276,6 +1382,14 @@ bool _execUpdater(bool update = true) {
args[argIndex++] = p_path;
args[argIndex++] = p_pathbuf;
}
if (!crashreport.isEmpty()) {
QByteArray crashreportf = crashreport.toUtf8();
if (crashreportf.size() < MaxLen) {
memcpy(p_crashreportbuf, crashreportf.constData(), crashreportf.size());
args[argIndex++] = p_crashreport;
args[argIndex++] = p_crashreportbuf;
}
}
pid_t pid = fork();
switch (pid) {
@ -1291,8 +1405,8 @@ void psExecUpdater() {
}
}
void psExecTelegram() {
_execUpdater(false);
void psExecTelegram(const QString &crashreport) {
_execUpdater(false, crashreport);
}
bool psShowOpenWithMenu(int x, int y, const QString &file) {

View File

@ -113,6 +113,10 @@ private:
uint64 _psLastIndicatorUpdate;
};
void psWriteDump();
void psWriteStackTrace(int file);
int psShowCrash(const QString &crashdump);
void psDeleteDir(const QString &dir);
void psUserActionDone();
@ -144,7 +148,7 @@ int psCleanup();
int psFixPrevious();
void psExecUpdater();
void psExecTelegram();
void psExecTelegram(const QString &arg = QString());
bool psShowOpenWithMenu(int x, int y, const QString &file);

View File

@ -2267,15 +2267,16 @@ void psExecUpdater() {
}
}
void psExecTelegram() {
QString targs = qsl("-noupdate");
if (cRestartingToSettings()) targs += qsl(" -tosettings");
if (cLaunchMode() == LaunchModeAutoStart) targs += qsl(" -autostart");
if (cDebug()) targs += qsl(" -debug");
if (cStartInTray()) targs += qsl(" -startintray");
if (cTestMode()) targs += qsl(" -testmode");
if (cDataFile() != qsl("data")) targs += qsl(" -key \"") + cDataFile() + '"';
void psExecTelegram(const QString &crashreport) {
QString targs = crashreport.isEmpty() ? qsl("-noupdate") : ('"' + crashreport + '"');
if (crashreport.isEmpty()) {
if (cRestartingToSettings()) targs += qsl(" -tosettings");
if (cLaunchMode() == LaunchModeAutoStart) targs += qsl(" -autostart");
if (cDebug()) targs += qsl(" -debug");
if (cStartInTray()) targs += qsl(" -startintray");
if (cTestMode()) targs += qsl(" -testmode");
if (cDataFile() != qsl("data")) targs += qsl(" -key \"") + cDataFile() + '"';
}
QString telegram(QDir::toNativeSeparators(cExeDir() + cExeName())), wdir(QDir::toNativeSeparators(cWorkingDir()));
DEBUG_LOG(("Application Info: executing %1 %2").arg(cExeDir() + cExeName()).arg(targs));
@ -3059,7 +3060,7 @@ void psWriteStackTrace(int file) {
#error "Platform not supported!"
#endif
for (frameNum = 0; frameNum < 1000; ++frameNum) {
for (frameNum = 0; frameNum < 1024; ++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

View File

@ -153,7 +153,7 @@ int psCleanup();
int psFixPrevious();
void psExecUpdater();
void psExecTelegram();
void psExecTelegram(const QString &arg = QString());
bool psShowOpenWithMenu(int x, int y, const QString &file);