4 #include <lib/base/eenv.h>
5 #include <lib/base/eerror.h>
6 #include <lib/base/nconfig.h>
7 #include <lib/gdi/gmaindc.h>
9 #if defined(__MIPSEL__)
10 #include <asm/ptrace.h>
12 #warning "no oops support!"
13 #define NO_OOPS_SUPPORT
16 #include "xmlgenerator.h"
17 #include "version_info.h"
19 /************************************************/
21 #ifdef BUILD_VUPLUS /* ikseong */
22 #define CRASH_EMAILADDR "crashlog"
24 #define CRASH_EMAILADDR "crashlog@dream-multimedia-tv.de"
26 #define INFOFILE "/maintainer.info"
28 #define RINGBUFFER_SIZE 16384
29 static char ringbuffer[RINGBUFFER_SIZE];
30 static unsigned int ringbuffer_head;
32 static void addToLogbuffer(const char *data, unsigned int len)
36 unsigned int remaining = RINGBUFFER_SIZE - ringbuffer_head;
41 memcpy(ringbuffer + ringbuffer_head, data, remaining);
44 ringbuffer_head += remaining;
45 ASSERT(ringbuffer_head <= RINGBUFFER_SIZE);
46 if (ringbuffer_head == RINGBUFFER_SIZE)
51 static const std::string getLogBuffer()
53 unsigned int begin = ringbuffer_head;
54 while (ringbuffer[begin] == 0)
57 if (begin == RINGBUFFER_SIZE)
59 if (begin == ringbuffer_head)
63 if (begin < ringbuffer_head)
64 return std::string(ringbuffer + begin, ringbuffer_head - begin);
66 return std::string(ringbuffer + begin, RINGBUFFER_SIZE - begin) + std::string(ringbuffer, ringbuffer_head);
69 static void addToLogbuffer(int level, const std::string &log)
71 addToLogbuffer(log.c_str(), log.size());
74 static const std::string getConfigString(const std::string &key, const std::string &defaultValue)
78 ePythonConfigQuery::getConfigValue(key.c_str(), value);
79 //we get at least the default value if python is still alive
85 // get value from enigma2 settings file
86 std::ifstream in(eEnv::resolve("${sysconfdir}/enigma2/settings").c_str());
90 std::getline(in, line);
91 size_t size = key.size();
92 if (!key.compare(0, size, line) && line[size] == '=') {
93 value = line.substr(size + 1);
103 static bool getConfigBool(const std::string &key, bool defaultValue)
105 std::string value = getConfigString(key, defaultValue ? "true" : "false");
106 const char *cvalue = value.c_str();
108 if (!strcasecmp(cvalue, "true"))
110 if (!strcasecmp(cvalue, "false"))
116 void bsodFatal(const char *component)
118 std::ostringstream os;
121 std::string logfile("/media/hdd/enigma2_crash_" + os.str() + ".log");
123 FILE *f = fopen(logfile.c_str(), "wb");
125 std::string lines = getLogBuffer();
127 /* find python-tracebacks, and extract " File "-strings */
130 std::string crash_emailaddr = CRASH_EMAILADDR;
131 std::string crash_component = "enigma2";
134 crash_component = component;
137 while ((start = lines.find("\n File \"", start)) != std::string::npos)
140 size_t end = lines.find("\"", start);
141 if (end == std::string::npos)
143 end = lines.rfind("/", end);
144 /* skip a potential prefix to the path */
145 unsigned int path_prefix = lines.find("/usr/", start);
146 if (path_prefix != std::string::npos && path_prefix < end)
149 if (end == std::string::npos)
152 std::string filename(lines.substr(start, end - start) + INFOFILE);
153 std::ifstream in(filename.c_str());
155 std::getline(in, crash_emailaddr) && std::getline(in, crash_component);
167 localtime_r(&t, &tm);
168 strftime(tm_str, sizeof(tm_str), "%a %b %_d %T %Y", &tm);
172 xml.open("opendreambox");
175 xml.string("crashdate", tm_str);
176 xml.string("compiledate", __DATE__);
177 xml.string("contactemail", crash_emailaddr);
178 xml.comment("Please email this crashlog to above address");
180 xml.string("skin", getConfigString("config.skin.primary_skin", "Default Skin"));
181 xml.string("sourcedate", enigma2_date);
182 xml.string("branch", enigma2_branch);
183 xml.string("rev", enigma2_rev);
184 xml.string("version", PACKAGE_VERSION);
188 xml.stringFromFile("dreamboxmodel", "/proc/stb/info/model");
189 xml.stringFromFile("kernelcmdline", "/proc/cmdline");
190 xml.stringFromFile("nimsockets", "/proc/bus/nim_sockets");
191 if (!getConfigBool("config.plugins.crashlogautosubmit.sendAnonCrashlog", true)) {
192 xml.cDataFromFile("dreamboxca", "/proc/stb/info/ca");
193 xml.cDataFromFile("enigma2settings", eEnv::resolve("${sysconfdir}/enigma2/settings"), ".password=");
195 if (getConfigBool("config.plugins.crashlogautosubmit.addNetwork", false)) {
196 xml.cDataFromFile("networkinterfaces", "/etc/network/interfaces");
197 xml.cDataFromFile("dns", "/etc/resolv.conf");
198 xml.cDataFromFile("defaultgateway", "/etc/default_gw");
200 if (getConfigBool("config.plugins.crashlogautosubmit.addWlan", false))
201 xml.cDataFromFile("wpasupplicant", "/etc/wpa_supplicant.conf");
202 xml.cDataFromFile("imageversion", "/etc/image-version");
203 xml.cDataFromFile("imageissue", "/etc/issue.net");
206 xml.open("software");
207 xml.cDataFromCmd("enigma2software", "ipkg list_installed | grep enigma2");
208 xml.cDataFromCmd("dreamboxsoftware", "ipkg list_installed | grep dream");
209 xml.cDataFromCmd("gstreamersoftware", "ipkg list_installed | grep gst");
212 xml.open("crashlogs");
213 xml.cDataFromString("enigma2crashlog", getLogBuffer());
214 xml.cDataFromCmd("pythonMD5sum", "find " + eEnv::resolve("${libdir}/enigma2/python/") + " -name \"*.py\" | xargs md5sum");
223 gMainDC::getInstance(my_dc);
227 p.resetClip(eRect(ePoint(0, 0), my_dc->size()));
228 p.setBackgroundColor(gRGB(0x008000));
229 p.setForegroundColor(gRGB(0xFFFFFF));
231 ePtr<gFont> font = new gFont("Regular", 20);
235 eRect usable_area = eRect(100, 70, my_dc->size().width() - 150, 100);
237 std::string text("We are really sorry. Your STB encountered "
238 "a software problem, and needs to be restarted. "
239 "Please send the logfile created in /hdd/ to " + crash_emailaddr + ".\n"
240 "Your STB restarts in 10 seconds!\n"
241 "Component: " + crash_component);
243 p.renderText(usable_area, text.c_str(), gPainter::RT_WRAP|gPainter::RT_HALIGN_LEFT);
245 usable_area = eRect(100, 170, my_dc->size().width() - 180, my_dc->size().height() - 20);
249 start = std::string::npos + 1;
252 start = lines.rfind('\n', start - 1);
253 if (start == std::string::npos)
260 font = new gFont("Regular", 14);
263 p.renderText(usable_area,
264 lines.substr(start), gPainter::RT_HALIGN_LEFT);
270 #if defined(__MIPSEL__)
271 void oops(const mcontext_t &context, int dumpcode)
273 eDebug("PC: %08lx", (unsigned long)context.pc);
277 eDebugNoNewLine(" %08x", (int)context.gregs[i]);
281 /* this is temporary debug stuff. */
282 if (dumpcode && ((unsigned long)context.pc) > 0x10000) /* not a zero pointer */
284 eDebug("As a final action, i will try to dump a bit of code.");
285 eDebug("I just hope that this won't crash.");
287 eDebugNoNewLine("%08lx:", (unsigned long)context.pc);
288 for (i=0; i<0x20; ++i)
289 eDebugNoNewLine(" %02x", ((unsigned char*)context.pc)[i]);
295 void handleFatalSignal(int signum, siginfo_t *si, void *ctx)
297 #ifndef NO_OOPS_SUPPORT
298 ucontext_t *uc = (ucontext_t*)ctx;
300 oops(uc->uc_mcontext, signum == SIGSEGV || signum == SIGABRT);
303 bsodFatal("enigma2, signal");
306 void bsodCatchSignals()
308 struct sigaction act;
309 act.sa_sigaction = handleFatalSignal;
310 act.sa_flags = SA_RESTART | SA_SIGINFO;
311 if (sigemptyset(&act.sa_mask) == -1)
312 perror("sigemptyset");
314 /* start handling segfaults etc. */
315 sigaction(SIGSEGV, &act, 0);
316 sigaction(SIGILL, &act, 0);
317 sigaction(SIGBUS, &act, 0);
318 sigaction(SIGABRT, &act, 0);
323 logOutput.connect(addToLogbuffer);