-#include <string.h>
-#include <signal.h>
-#include <asm/ptrace.h>
-
+#include <csignal>
+#include <fstream>
+#include <sstream>
+#include <lib/base/eenv.h>
#include <lib/base/eerror.h>
-#include <lib/base/smartptr.h>
-#include <lib/gdi/grc.h>
-#include <lib/gdi/gfbdc.h>
-#ifdef WITH_SDL
-#include <lib/gdi/sdl.h>
+#include <lib/base/nconfig.h>
+#include <lib/gdi/gmaindc.h>
+
+#if defined(__MIPSEL__)
+#include <asm/ptrace.h>
+#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;
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)
addToLogbuffer(log.c_str(), log.size());
}
+static const std::string getConfigString(const std::string &key, const std::string &defaultValue)
+{
+ std::string value;
+
+ ePythonConfigQuery::getConfigValue(key.c_str(), value);
+ //we get at least the default value if python is still alive
+ if (!value.empty())
+ return value;
+
+ value = defaultValue;
+
+ // 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;
-extern std::string getLogBuffer();
+ return defaultValue;
+}
-void bsodFatal()
+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;
+
+ std::string crash_emailaddr = CRASH_EMAILADDR;
+ std::string crash_component = "enigma2";
+
+ if (component)
+ crash_component = component;
+ else
+ {
+ while ((start = lines.find("\n File \"", start)) != std::string::npos)
+ {
+ 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 " CRASH_EMAILADDR "\n");
- 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<gSDLDC> my_dc;
- gSDLDC::getInstance(my_dc);
-#else
- ePtr<gFBDC> 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<gFont> font = new gFont("Regular", 20);
- p.setFont(font);
- p.clear();
-
- eRect usable_area = eRect(100, 70, my_dc->size().width() - 150, 100);
+ ePtr<gMainDC> my_dc;
+ gMainDC::getInstance(my_dc);
- p.renderText(usable_area,
- "We are really sorry. Something happened "
- "which should not have happened, and "
- "resulted in a crash. If you want to help "
- "us in improving this situation, please send "
- "the logfile created in /hdd/ to " CRASH_EMAILADDR "."
- "Your receiver restarts in 10 seconds !", gPainter::RT_WRAP|gPainter::RT_HALIGN_LEFT);
-
- usable_area = eRect(100, 170, my_dc->size().width() - 180, my_dc->size().height() - 20);
-
- 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<gFont> 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);
}
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)