X-Git-Url: https://git.cweiske.de/enigma2.git/blobdiff_plain/a34ef895210161a8820e96829ac87806566e7858..99f2eac17b09061f69ac92bc4d06b2f3e5576e5a:/main/bsod.cpp diff --git a/main/bsod.cpp b/main/bsod.cpp index 173a2cce..a1194328 100644 --- a/main/bsod.cpp +++ b/main/bsod.cpp @@ -1,46 +1,52 @@ -#include -#include -#include - +#include +#include +#include +#include #include -#include -#include -#include -#ifdef WITH_SDL -#include +#include +#include + +#if defined(__MIPSEL__) +#include +#else +#warning "no oops support!" +#define NO_OOPS_SUPPORT #endif -#include "version.h" +#include "xmlgenerator.h" +#include "version_info.h" /************************************************/ #define CRASH_EMAILADDR "crashlog@dream-multimedia-tv.de" +#define INFOFILE "/maintainer.info" #define RINGBUFFER_SIZE 16384 static char ringbuffer[RINGBUFFER_SIZE]; -static int ringbuffer_head; +static unsigned int ringbuffer_head; -static void addToLogbuffer(const char *data, int len) +static void addToLogbuffer(const char *data, unsigned int len) { while (len) { - int remaining = RINGBUFFER_SIZE - ringbuffer_head; - + unsigned int remaining = RINGBUFFER_SIZE - ringbuffer_head; + if (remaining > len) remaining = len; - + memcpy(ringbuffer + ringbuffer_head, data, remaining); len -= remaining; data += remaining; ringbuffer_head += remaining; - if (ringbuffer_head >= RINGBUFFER_SIZE) + ASSERT(ringbuffer_head <= RINGBUFFER_SIZE); + if (ringbuffer_head == RINGBUFFER_SIZE) ringbuffer_head = 0; } } -static std::string getLogBuffer() +static const std::string getLogBuffer() { - int begin = ringbuffer_head; + unsigned int begin = ringbuffer_head; while (ringbuffer[begin] == 0) { ++begin; @@ -49,12 +55,11 @@ static std::string getLogBuffer() if (begin == ringbuffer_head) return ""; } + if (begin < ringbuffer_head) return std::string(ringbuffer + begin, ringbuffer_head - begin); else - { return std::string(ringbuffer + begin, RINGBUFFER_SIZE - begin) + std::string(ringbuffer, ringbuffer_head); - } } static void addToLogbuffer(int level, const std::string &log) @@ -62,147 +67,199 @@ static void addToLogbuffer(int level, const std::string &log) addToLogbuffer(log.c_str(), log.size()); } +static const std::string getConfigString(const std::string &key, const std::string &defaultValue) +{ + std::string value; -extern std::string getLogBuffer(); + ePythonConfigQuery::getConfigValue(key.c_str(), value); + //we get at least the default value if python is still alive + if (!value.empty()) + return value; -#define INFOFILE "/maintainer.info" + value = defaultValue; -void bsodFatal() + // get value from enigma2 settings file + std::ifstream in(eEnv::resolve("${sysconfdir}/enigma2/settings").c_str()); + if (in.good()) { + do { + std::string line; + std::getline(in, line); + size_t size = key.size(); + if (!key.compare(0, size, line) && line[size] == '=') { + value = line.substr(size + 1); + break; + } + } while (in.good()); + in.close(); + } + + return value; +} + +static bool getConfigBool(const std::string &key, bool defaultValue) +{ + std::string value = getConfigString(key, defaultValue ? "true" : "false"); + const char *cvalue = value.c_str(); + + if (!strcasecmp(cvalue, "true")) + return true; + if (!strcasecmp(cvalue, "false")) + return false; + + return defaultValue; +} + +void bsodFatal(const char *component) { - char logfile[128]; - sprintf(logfile, "/media/hdd/enigma2_crash_%u.log", (unsigned int)time(0)); - FILE *f = fopen(logfile, "wb"); + std::ostringstream os; + os << time(0); + + std::string logfile("/media/hdd/enigma2_crash_" + os.str() + ".log"); + + FILE *f = fopen(logfile.c_str(), "wb"); std::string lines = getLogBuffer(); /* find python-tracebacks, and extract " File "-strings */ size_t start = 0; - char crash_emailaddr[256] = CRASH_EMAILADDR; - char crash_component[256] = "enigma2"; + std::string crash_emailaddr = CRASH_EMAILADDR; + std::string crash_component = "enigma2"; - while ((start = lines.find("\n File \"", start)) != std::string::npos) + if (component) + crash_component = component; + else { - start += 9; - size_t end = lines.find("\"", start); - if (end == std::string::npos) - break; - end = lines.rfind("/", end); - if (end == std::string::npos) - break; - if (end - start >= (256 - strlen(INFOFILE))) - continue; - char filename[256]; - snprintf(filename, 256, "%s%s", lines.substr(start, end - start).c_str(), INFOFILE); - FILE *cf = fopen(filename, "r"); - if (cf) + while ((start = lines.find("\n File \"", start)) != std::string::npos) { - fgets(crash_emailaddr, sizeof crash_emailaddr, cf); - if (*crash_emailaddr && crash_emailaddr[strlen(crash_emailaddr)-1] == '\n') - crash_emailaddr[strlen(crash_emailaddr)-1] = 0; - - fgets(crash_component, sizeof crash_component, cf); - if (*crash_component && crash_component[strlen(crash_component)-1] == '\n') - crash_component[strlen(crash_component)-1] = 0; - fclose(cf); + start += 9; + size_t end = lines.find("\"", start); + if (end == std::string::npos) + break; + end = lines.rfind("/", end); + /* skip a potential prefix to the path */ + unsigned int path_prefix = lines.find("/usr/", start); + if (path_prefix != std::string::npos && path_prefix < end) + start = path_prefix; + + if (end == std::string::npos) + break; + + std::string filename(lines.substr(start, end - start) + INFOFILE); + std::ifstream in(filename.c_str()); + if (in.good()) { + std::getline(in, crash_emailaddr) && std::getline(in, crash_component); + in.close(); + } } } if (f) { time_t t = time(0); - fprintf(f, "enigma2 crashed on %s", ctime(&t)); -#ifdef ENIGMA2_CHECKOUT_TAG - fprintf(f, "enigma2 CVS TAG: " ENIGMA2_CHECKOUT_TAG "\n"); -#else - fprintf(f, "enigma2 compiled on " __DATE__ "\n"); -#endif -#ifdef ENIGMA2_CHECKOUT_ROOT - fprintf(f, "enigma2 checked out from " ENIGMA2_CHECKOUT_ROOT "\n"); -#endif - fprintf(f, "please email this file to %s\n", crash_emailaddr); - std::string buffer = getLogBuffer(); - fwrite(buffer.c_str(), buffer.size(), 1, f); + struct tm tm; + char tm_str[32]; + + localtime_r(&t, &tm); + strftime(tm_str, sizeof(tm_str), "%a %b %_d %T %Y", &tm); + + XmlGenerator xml(f); + + xml.open("opendreambox"); + + xml.open("enigma2"); + xml.string("crashdate", tm_str); + xml.string("compiledate", __DATE__); + xml.string("contactemail", crash_emailaddr); + xml.comment("Please email this crashlog to above address"); + + xml.string("skin", getConfigString("config.skin.primary_skin", "Default Skin")); + xml.string("sourcedate", enigma2_date); + xml.string("branch", enigma2_branch); + xml.string("rev", enigma2_rev); + xml.string("version", PACKAGE_VERSION); + xml.close(); + + xml.open("image"); + xml.stringFromFile("dreamboxmodel", "/proc/stb/info/model"); + xml.stringFromFile("kernelcmdline", "/proc/cmdline"); + xml.stringFromFile("nimsockets", "/proc/bus/nim_sockets"); + if (!getConfigBool("config.plugins.crashlogautosubmit.sendAnonCrashlog", true)) { + xml.cDataFromFile("dreamboxca", "/proc/stb/info/ca"); + xml.cDataFromFile("enigma2settings", eEnv::resolve("${sysconfdir}/enigma2/settings"), ".password="); + } + if (getConfigBool("config.plugins.crashlogautosubmit.addNetwork", false)) { + xml.cDataFromFile("networkinterfaces", "/etc/network/interfaces"); + xml.cDataFromFile("dns", "/etc/resolv.conf"); + xml.cDataFromFile("defaultgateway", "/etc/default_gw"); + } + if (getConfigBool("config.plugins.crashlogautosubmit.addWlan", false)) + xml.cDataFromFile("wpasupplicant", "/etc/wpa_supplicant.conf"); + xml.cDataFromFile("imageversion", "/etc/image-version"); + xml.cDataFromFile("imageissue", "/etc/issue.net"); + xml.close(); + + xml.open("software"); + xml.cDataFromCmd("enigma2software", "opkg list_installed | grep enigma2"); + xml.cDataFromCmd("dreamboxsoftware", "opkg list_installed | grep dream"); + xml.cDataFromCmd("gstreamersoftware", "opkg list_installed | grep gst"); + xml.close(); + + xml.open("crashlogs"); + xml.cDataFromString("enigma2crashlog", getLogBuffer()); + xml.cDataFromCmd("pythonMD5sum", "find " + eEnv::resolve("${libdir}/enigma2/python/") + " -name \"*.py\" | xargs md5sum"); + xml.close(); + + xml.close(); + fclose(f); - - char cmd[256]; - sprintf(cmd, "find /usr/lib/enigma2/python/ -name \"*.py\" | xargs md5sum >> %s", logfile); - system(cmd); } - -#ifdef WITH_SDL - ePtr my_dc; - gSDLDC::getInstance(my_dc); -#else - ePtr my_dc; - gFBDC::getInstance(my_dc); -#endif - - { - gPainter p(my_dc); - p.resetOffset(); - p.resetClip(eRect(ePoint(0, 0), my_dc->size())); -#ifdef ENIGMA2_CHECKOUT_TAG - if (ENIGMA2_CHECKOUT_TAG[0] == 'T') /* tagged checkout (release) */ - p.setBackgroundColor(gRGB(0x0000C0)); - else if (ENIGMA2_CHECKOUT_TAG[0] == 'D') /* dated checkout (daily experimental build) */ - { - srand(time(0)); - int r = rand(); - unsigned int col = 0; - if (r & 1) - col |= 0x800000; - if (r & 2) - col |= 0x008000; - if (r & 4) - col |= 0x0000c0; - p.setBackgroundColor(gRGB(col)); - } -#else - p.setBackgroundColor(gRGB(0x008000)); -#endif - p.setForegroundColor(gRGB(0xFFFFFF)); - - ePtr font = new gFont("Regular", 20); - p.setFont(font); - p.clear(); - - eRect usable_area = eRect(100, 70, my_dc->size().width() - 150, 100); - - char text[512]; - snprintf(text, 512, "We are really sorry. Your Dreambox encountered " - "a software problem, and needs to be restarted. " - "Please send the logfile created in /hdd/ to %s.\n" - "Your Dreambox restarts in 10 seconds!\n" - "Component: %s", - crash_emailaddr, crash_component); - - p.renderText(usable_area, text, gPainter::RT_WRAP|gPainter::RT_HALIGN_LEFT); - - usable_area = eRect(100, 170, my_dc->size().width() - 180, my_dc->size().height() - 20); + ePtr my_dc; + gMainDC::getInstance(my_dc); - int i; + gPainter p(my_dc); + p.resetOffset(); + p.resetClip(eRect(ePoint(0, 0), my_dc->size())); + p.setBackgroundColor(gRGB(0x008000)); + p.setForegroundColor(gRGB(0xFFFFFF)); + + ePtr font = new gFont("Regular", 20); + p.setFont(font); + p.clear(); + + eRect usable_area = eRect(100, 70, my_dc->size().width() - 150, 100); - size_t start = std::string::npos + 1; - for (i=0; i<20; ++i) + std::string text("We are really sorry. Your Dreambox encountered " + "a software problem, and needs to be restarted. " + "Please send the logfile created in /hdd/ to " + crash_emailaddr + ".\n" + "Your Dreambox restarts in 10 seconds!\n" + "Component: " + crash_component); + + p.renderText(usable_area, text.c_str(), gPainter::RT_WRAP|gPainter::RT_HALIGN_LEFT); + + usable_area = eRect(100, 170, my_dc->size().width() - 180, my_dc->size().height() - 20); + + int i; + + start = std::string::npos + 1; + for (i=0; i<20; ++i) + { + start = lines.rfind('\n', start - 1); + if (start == std::string::npos) { - start = lines.rfind('\n', start - 1); - if (start == std::string::npos) - { - start = 0; - break; - } + start = 0; + break; } - - font = new gFont("Regular", 14); - p.setFont(font); - - p.renderText(usable_area, - lines.substr(start), gPainter::RT_HALIGN_LEFT); - sleep(10); } + font = new gFont("Regular", 14); + p.setFont(font); + + p.renderText(usable_area, + lines.substr(start), gPainter::RT_HALIGN_LEFT); + sleep(10); + raise(SIGKILL); } @@ -229,26 +286,22 @@ void oops(const mcontext_t &context, int dumpcode) eDebug(" (end)"); } } -#else -#warning "no oops support!" -#define NO_OOPS_SUPPORT #endif void handleFatalSignal(int signum, siginfo_t *si, void *ctx) { - ucontext_t *uc = (ucontext_t*)ctx; - eDebug("KILLED BY signal %d", signum); #ifndef NO_OOPS_SUPPORT + ucontext_t *uc = (ucontext_t*)ctx; + oops(uc->uc_mcontext, signum == SIGSEGV || signum == SIGABRT); #endif eDebug("-------"); - bsodFatal(); + bsodFatal("enigma2, signal"); } void bsodCatchSignals() { struct sigaction act; - act.sa_handler = SIG_DFL; act.sa_sigaction = handleFatalSignal; act.sa_flags = SA_RESTART | SA_SIGINFO; if (sigemptyset(&act.sa_mask) == -1)