diff options
-rw-r--r-- | BuildConfig.cpp.in | 2 | ||||
-rw-r--r-- | BuildConfig.h | 4 | ||||
-rw-r--r-- | CMakeLists.txt | 30 | ||||
-rw-r--r-- | HandleCrash.cpp | 375 | ||||
-rw-r--r-- | HandleCrash.h | 18 | ||||
-rw-r--r-- | MultiMC.cpp | 3 | ||||
-rw-r--r-- | MultiMC.h | 4 | ||||
-rw-r--r-- | main.cpp | 10 |
8 files changed, 0 insertions, 446 deletions
diff --git a/BuildConfig.cpp.in b/BuildConfig.cpp.in index 76196b7e..1ea07374 100644 --- a/BuildConfig.cpp.in +++ b/BuildConfig.cpp.in @@ -29,9 +29,7 @@ Config::Config() UPDATER_FORCE_LOCAL = @MultiMC_UPDATER_FORCE_LOCAL_value@; GIT_COMMIT = "@MultiMC_GIT_COMMIT@"; - GIT_COMMIT_CSTR = "@MultiMC_GIT_COMMIT@"; VERSION_STR = "@MultiMC_VERSION_STRING@"; - VERSION_CSTR = "@MultiMC_VERSION_STRING@"; NEWS_RSS_URL = "@MultiMC_NEWS_RSS_URL@"; } diff --git a/BuildConfig.h b/BuildConfig.h index 5e10beb0..baf2ad6d 100644 --- a/BuildConfig.h +++ b/BuildConfig.h @@ -61,14 +61,10 @@ public: /// The commit hash of this build QString GIT_COMMIT; - const char* GIT_COMMIT_CSTR; /// This is printed on start to standard output QString VERSION_STR; - /// Version string as a char string. Used by the crash handling system to avoid touching heap memory. - const char* VERSION_CSTR; - /** * This is used to fetch the news RSS feed. * It defaults in CMakeLists.txt to "http://multimc.org/rss.xml" diff --git a/CMakeLists.txt b/CMakeLists.txt index 70031bd2..77c4770c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -77,33 +77,9 @@ if(${BIGENDIAN}) add_definitions(-DMULTIMC_BIG_ENDIAN) endif(${BIGENDIAN}) - -######## Dark magic crash reports ######## -option(MultiMC_HANDLE_SEGV "Handle fatal crashes and generate crash reports." OFF) -set(CRASH_HANDLER_IMPL "") -message(STATUS "Crash dumps are ${MultiMC_HANDLE_SEGV}") -if (MultiMC_HANDLE_SEGV) - add_definitions(-DHANDLE_SEGV) - if (WIN32) - find_package(DbgHelp) - set(MultiMC_LINK_ADDITIONAL_LIBS "${MultiMC_LINK_ADDITIONAL_LIBS}dbghelp") - set(MultiMC_CRASH_HANDLER_EXTRA_H "WinBacktrace.h") - set(MultiMC_CRASH_HANDLER_EXTRA_CPP "WinBacktrace.cpp") - endif () -endif () - -option(MultiMC_TEST_SEGV "Intentionally segfault sometimes to test crash handling." OFF) -if (MultiMC_TEST_SEGV) - # TODO: Make this a unit test instead. - message(WARNING "You have enabled crash handler testing. MULTIMC WILL INTENTIONALLY CRASH ITSELF. Crashes should occur on exit and when the new instance button is pressed.") - add_definitions(-DTEST_SEGV) -endif () - - ######## Set URLs ######## set(MultiMC_NEWS_RSS_URL "http://multimc.org/rss.xml" CACHE STRING "URL to fetch MultiMC's news RSS feed from.") - ######## Set version numbers ######## set(MultiMC_VERSION_MAJOR 0) set(MultiMC_VERSION_MINOR 5) @@ -279,12 +255,6 @@ SET(MULTIMC_SOURCES BuildConfig.h ${PROJECT_BINARY_DIR}/BuildConfig.cpp - # Crash handling - HandleCrash.h - HandleCrash.cpp - ${MultiMC_CRASH_HANDLER_EXTRA_H} # Extra platform specific stuff - ${MultiMC_CRASH_HANDLER_EXTRA_CPP} - # Logging logger/QsDebugOutput.cpp logger/QsDebugOutput.h diff --git a/HandleCrash.cpp b/HandleCrash.cpp deleted file mode 100644 index f8a5d5d5..00000000 --- a/HandleCrash.cpp +++ /dev/null @@ -1,375 +0,0 @@ -/* Copyright 2013-2014 MultiMC Contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// This is the Unix implementation of MultiMC's crash handling system. -#include <stdio.h> -#include <iostream> -#include <signal.h> -#include <stdlib.h> -#include <unistd.h> -#include <time.h> -#include <fcntl.h> -#include <errno.h> -#include <sys/stat.h> - -#include <MultiMC.h> - -#if defined Q_OS_UNIX -#include <sys/utsname.h> -#include <execinfo.h> -#elif defined Q_OS_WIN32 -#include <windows.h> -#include <dbghelp.h> -#include <WinBacktrace.h> -#endif - -#include "BuildConfig.h" - -#include "HandleCrash.h" - -// The maximum number of frames to include in the backtrace. -#define BT_SIZE 20 - - -#define DUMPF_NAME_FMT "mmc-crash-%X.bm" // Black magic? Bowel movement? Dump? -// 1234567890 1234 -// The maximum number of digits in a unix timestamp when encoded in hexadecimal is about 17. -// Our format string is ~14 characters long. -// The maximum length of the dump file's filename should be well over both of these. 42 is a good number. -#define DUMPF_NAME_LEN 42 - -// {{{ Platform hackery - -#if defined Q_OS_UNIX - -struct CrashData -{ - int signal = 0; -}; - -// This has to be declared here, after the CrashData struct, but before the function that uses it. -void handleCrash(CrashData); - -void handler(int sig) -{ - CrashData cData; - cData.signal = sig; - handleCrash(cData); -} - -#elif defined Q_OS_WIN32 - -// Struct for storing platform specific crash information. -// This gets passed into the generic handler, which will use -// it to access platform specific information. -struct CrashData -{ - EXCEPTION_RECORD* exceptionInfo; - CONTEXT* context; -}; - -void handleCrash(CrashData); - -LONG WINAPI ExceptionFilter(EXCEPTION_POINTERS* eInfo) -{ - CrashData cData; - cData.exceptionInfo = eInfo->ExceptionRecord; - cData.context = eInfo->ContextRecord; - handleCrash(cData); - return EXCEPTION_EXECUTE_HANDLER; -} - -#endif - -// }}} - -// {{{ Handling - -#ifdef Q_OS_WIN32 -// #ThanksMicrosoft -// Blame Microsoft for this atrocity. -void dprintf(int fd, const char* fmt...) -{ - va_list args; - va_start(args, fmt); - char buffer[10240]; - // Just sprintf to a really long string and hope it works... - // This is a hack, but I can't think of a better way to do it easily. - int len = vsnprintf(buffer, 10240, fmt, args); - printf(buffer, fmt, args); - write(fd, buffer, len); - va_end(args); -} -#endif - -void getVsnType(char* out); -void readFromTo(int from, int to); - -void dumpErrorInfo(int dumpFile, CrashData crash) -{ -#ifdef Q_OS_UNIX - // TODO: Moar unix - dprintf(dumpFile, "Signal: %d\n", crash.signal); -#elif defined Q_OS_WIN32 - EXCEPTION_RECORD* excInfo = crash.exceptionInfo; - - dprintf(dumpFile, "Exception Code: %d\n", excInfo->ExceptionCode); - dprintf(dumpFile, "Exception Address: 0x%0X\n", excInfo->ExceptionAddress); -#endif -} - -void dumpMiscInfo(int dumpFile) -{ - char vsnType[42]; // The version type. If it's more than 42 chars, the universe might implode... - - // Get MMC info. - getVsnType(vsnType); - - // Get MMC info. - getVsnType(vsnType); - - dprintf(dumpFile, "MultiMC Version: %s\n", BuildConfig.VERSION_CSTR); - dprintf(dumpFile, "MultiMC Version Type: %s\n", vsnType); -} - -void dumpBacktrace(int dumpFile, CrashData crash) -{ -#ifdef Q_OS_UNIX - // Variables for storing crash info. - void* trace[BT_SIZE]; // Backtrace frames - size_t size; // The backtrace size - - // Get the backtrace. - size = backtrace(trace, BT_SIZE); - - // Dump the backtrace - dprintf(dumpFile, "---- BEGIN BACKTRACE ----\n"); - backtrace_symbols_fd(trace, size, dumpFile); - dprintf(dumpFile, "---- END BACKTRACE ----\n"); -#elif defined Q_OS_WIN32 - dprintf(dumpFile, "---- BEGIN BACKTRACE ----\n"); - - StackFrame stack[BT_SIZE]; - size_t size; - - SYMBOL_INFO *symbol; - HANDLE process; - - size = getBacktrace(stack, BT_SIZE, *crash.context); - - // FIXME: Accessing heap memory is supposedly "dangerous", - // but I can't find another way of doing this. - - // Initialize - process = GetCurrentProcess(); - if (!SymInitialize(process, NULL, true)) - { - dprintf(dumpFile, "Failed to initialize symbol handler. Can't print stack trace.\n"); - dprintf(dumpFile, "Here's a list of addresses in the call stack instead:\n"); - for(int i = 0; i < size; i++) - { - dprintf(dumpFile, "0x%0X\n", (DWORD64)stack[i].address); - } - } else { - // Allocate memory... ._. - symbol = (SYMBOL_INFO *) calloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char), 1); - symbol->MaxNameLen = 255; - symbol->SizeOfStruct = sizeof(SYMBOL_INFO); - - // Dump stacktrace - for(int i = 0; i < size; i++) - { - DWORD64 addr = (DWORD64)stack[i].address; - if (!SymFromAddr(process, (DWORD64)(addr), 0, symbol)) - dprintf(dumpFile, "?? - 0x%0X\n", addr); - else - dprintf(dumpFile, "%s - 0x%0X\n", symbol->Name, symbol->Address); - } - - free(symbol); - } - - dprintf(dumpFile, "---- END BACKTRACE ----\n"); -#endif -} - -void dumpSysInfo(int dumpFile) -{ -#ifdef Q_OS_UNIX - utsname sysinfo; // System information - - // Dump system info - if (uname(&sysinfo) >= 0) - { - dprintf(dumpFile, "OS System: %s\n", sysinfo.sysname); - dprintf(dumpFile, "OS Machine: %s\n", sysinfo.machine); - dprintf(dumpFile, "OS Release: %s\n", sysinfo.release); - dprintf(dumpFile, "OS Version: %s\n", sysinfo.version); - } else { - dprintf(dumpFile, "OS System: Unknown Unix"); - } -#else - // TODO: Get more information here. - dprintf(dumpFile, "OS System: Windows"); -#endif -} - -void dumpLogs(int dumpFile) -{ - int otherFile; - - // Attempt to attach the log file if the logger was initialized. - dprintf(dumpFile, "---- BEGIN LOGS ----\n"); - if (loggerInitialized) - { - otherFile = open("MultiMC-0.log", O_RDONLY); - readFromTo(otherFile, dumpFile); - } else { - dprintf(dumpFile, "Logger not initialized.\n"); - } - dprintf(dumpFile, "---- END LOGS ----\n"); -} - -// The signal handler. If this function is called, it means shit has probably collided with some sort of device one might use to keep oneself cool. -// This is the generic part of the code that will be called after platform specific handling is finished. -void handleCrash(CrashData crash) -{ -#ifdef Q_OS_UNIX - fprintf(stderr, "Fatal error! Received signal %d\n", crash.signal); -#endif - - time_t unixTime = 0; // Unix timestamp. Used to give our crash dumps "unique" names. - - char dumpFileName[DUMPF_NAME_LEN]; // The name of the file we're dumping to. - int dumpFile; // File descriptor for our dump file. - - // Determine what our dump file should be called. - // We'll just call it "mmc-crash-<unixtime>.dump" - // First, check the time. - time(&unixTime); - - // Now we get to do some !!FUN!! hackery to ensure we don't use the stack when we convert - // the timestamp from an int to a string. To do this, we just allocate a fixed size array - // of chars on the stack, and sprintf into it. We know the timestamp won't ever be longer - // than a certain number of digits, so this should work just fine. - // sprintf doesn't support writing signed values as hex, so this breaks on negative timestamps. - // It really shouldn't matter, though... - sprintf(dumpFileName, DUMPF_NAME_FMT, unixTime); - - // Now, we need to open the file. - // Fail if it already exists. This should never happen. - dumpFile = open(dumpFileName, O_WRONLY | O_CREAT | O_TRUNC, 0644); - - - if (dumpFile >= 0) - { - // If we opened the dump file successfully. - // Dump everything we can and GTFO. - fprintf(stderr, "Dumping crash report to %s\n", dumpFileName); - - // Dump misc info - dprintf(dumpFile, "Unix Time: %d\n", unixTime); - dumpErrorInfo(dumpFile, crash); - dumpMiscInfo(dumpFile); - - dprintf(dumpFile, "\n"); - - dumpSysInfo(dumpFile); - - dprintf(dumpFile, "\n"); - - dumpBacktrace(dumpFile, crash); - - dprintf(dumpFile, "\n"); - - // DIE DIE DIE! - exit(1); - } - else - { - fprintf(stderr, "Failed to open dump file %s to write crash info (ERRNO: %d)\n", dumpFileName, errno); - exit(2); - } -} - - -// Reads data from the file descriptor on the first argument into the second argument. -void readFromTo(int from, int to) -{ - char buffer[1024]; - size_t lastread = 1; - while (lastread > 0) - { - lastread = read(from, buffer, 1024); - if (lastread > 0) write(to, buffer, lastread); - } -} - -// Writes the current version type to the given char buffer. -void getVsnType(char* out) -{ - switch (BuildConfig.versionTypeEnum) - { - case Config::Release: - sprintf(out, "Release"); - break; - case Config::ReleaseCandidate: - sprintf(out, "ReleaseCandidate"); - break; - case Config::Development: - sprintf(out, "Development"); - break; - default: - sprintf(out, "Unknown"); - break; - } -} - -// }}} - -// {{{ Misc - -#if defined TEST_SEGV -// Causes a crash. For testing. -void testCrash() -{ - char* lol = (char*)MMC->settings().get(); - lol -= 8; - - // Throw shit at the fan. - for (int i = 0; i < 8; i++) - lol[i] = 'f'; -} -#endif - -// Initializes the Unix crash handler. -void initBlackMagic() -{ -#ifdef Q_OS_UNIX - // Register the handler. - signal(SIGSEGV, handler); - signal(SIGABRT, handler); -#elif defined Q_OS_WIN32 - // I hate Windows - SetUnhandledExceptionFilter(ExceptionFilter); -#endif - -#ifdef TEST_SEGV - testCrash(); -#endif -} - -// }}} - diff --git a/HandleCrash.h b/HandleCrash.h deleted file mode 100644 index 3b2e7d00..00000000 --- a/HandleCrash.h +++ /dev/null @@ -1,18 +0,0 @@ -// This is a simple header file for the crash handling system. It exposes only one method, -// initBlackMagic, which initializes the system, registering signal handlers, or doing -// whatever stupid things need to be done on Windows. -// The platform specific implementations for this system are in UnixCrash.cpp and -// WinCrash.cpp. - -#if defined Q_OS_WIN -#warning Crash handling is not yet implemented on Windows. -#elif defined Q_OS_UNIX -#else -#warning Crash handling is not supported on this platform. -#endif - -/** - * Initializes the crash handling system. - */ -void initBlackMagic(); - diff --git a/MultiMC.cpp b/MultiMC.cpp index 222d7c89..610097f1 100644 --- a/MultiMC.cpp +++ b/MultiMC.cpp @@ -358,11 +358,8 @@ void MultiMC::initLogger() logger.addDestination(m_debugDestination.get()); // log all the things logger.setLoggingLevel(QsLogging::TraceLevel); - loggerInitialized = true; } -bool loggerInitialized = false; - void MultiMC::initGlobalSettings(bool test_mode) { m_settings.reset(new INISettingsObject("multimc.cfg", this)); @@ -41,10 +41,6 @@ enum UpdateFlag Q_DECLARE_FLAGS(UpdateFlags, UpdateFlag); Q_DECLARE_OPERATORS_FOR_FLAGS(UpdateFlags); -// Global var used by the crash handling system to determine if a log file should be included in -// a crash report. -extern bool loggerInitialized; - class MultiMC : public QApplication { Q_OBJECT @@ -1,12 +1,6 @@ #include "MultiMC.h" #include "gui/MainWindow.h" -// Crash handling -#ifdef HANDLE_SEGV -#include <HandleCrash.h> -#endif - - int main_gui(MultiMC &app) { // show main window @@ -31,10 +25,6 @@ int main(int argc, char *argv[]) Q_INIT_RESOURCE(backgrounds); Q_INIT_RESOURCE(versions); -#ifdef HANDLE_SEGV - // Register signal handler for generating crash reports. - initBlackMagic(); -#endif Q_INIT_RESOURCE(pe_dark); Q_INIT_RESOURCE(pe_light); Q_INIT_RESOURCE(pe_blue); |