3 #include <asm/ptrace.h>
5 #include <lib/base/eerror.h>
6 #include <lib/base/smartptr.h>
7 #include <lib/gdi/grc.h>
8 #include <lib/gdi/gfbdc.h>
10 #include <lib/gdi/sdl.h>
15 /************************************************/
17 #define CRASH_EMAILADDR "crashlog@dream-multimedia-tv.de"
19 #define RINGBUFFER_SIZE 16384
20 static char ringbuffer[RINGBUFFER_SIZE];
21 static int ringbuffer_head;
23 static void addToLogbuffer(const char *data, int len)
27 int remaining = RINGBUFFER_SIZE - ringbuffer_head;
32 memcpy(ringbuffer + ringbuffer_head, data, remaining);
35 ringbuffer_head += remaining;
36 if (ringbuffer_head >= RINGBUFFER_SIZE)
41 static std::string getLogBuffer()
43 int begin = ringbuffer_head;
44 while (ringbuffer[begin] == 0)
47 if (begin == RINGBUFFER_SIZE)
49 if (begin == ringbuffer_head)
52 if (begin < ringbuffer_head)
53 return std::string(ringbuffer + begin, ringbuffer_head - begin);
56 return std::string(ringbuffer + begin, RINGBUFFER_SIZE - begin) + std::string(ringbuffer, ringbuffer_head);
60 static void addToLogbuffer(int level, const std::string &log)
62 addToLogbuffer(log.c_str(), log.size());
66 extern std::string getLogBuffer();
68 #define INFOFILE "/maintainer.info"
70 void bsodFatal(const char *component)
73 sprintf(logfile, "/media/hdd/enigma2_crash_%u.log", (unsigned int)time(0));
74 FILE *f = fopen(logfile, "wb");
76 std::string lines = getLogBuffer();
78 /* find python-tracebacks, and extract " File "-strings */
81 char crash_emailaddr[256] = CRASH_EMAILADDR;
82 char crash_component[256] = "enigma2";
85 snprintf(crash_component, 256, component);
88 while ((start = lines.find("\n File \"", start)) != std::string::npos)
91 size_t end = lines.find("\"", start);
92 if (end == std::string::npos)
94 end = lines.rfind("/", end);
95 /* skip a potential prefix to the path */
96 unsigned int path_prefix = lines.find("/usr/", start);
97 if (path_prefix != std::string::npos && path_prefix < end)
100 if (end == std::string::npos)
102 if (end - start >= (256 - strlen(INFOFILE)))
105 snprintf(filename, 256, "%s%s", lines.substr(start, end - start).c_str(), INFOFILE);
106 FILE *cf = fopen(filename, "r");
109 fgets(crash_emailaddr, sizeof crash_emailaddr, cf);
110 if (*crash_emailaddr && crash_emailaddr[strlen(crash_emailaddr)-1] == '\n')
111 crash_emailaddr[strlen(crash_emailaddr)-1] = 0;
113 fgets(crash_component, sizeof crash_component, cf);
114 if (*crash_component && crash_component[strlen(crash_component)-1] == '\n')
115 crash_component[strlen(crash_component)-1] = 0;
124 fprintf(f, "enigma2 crashed on %s", ctime(&t));
125 #ifdef ENIGMA2_CHECKOUT_TAG
126 fprintf(f, "enigma2 CVS TAG: " ENIGMA2_CHECKOUT_TAG "\n");
128 fprintf(f, "enigma2 compiled on " __DATE__ "\n");
130 #ifdef ENIGMA2_CHECKOUT_ROOT
131 fprintf(f, "enigma2 checked out from " ENIGMA2_CHECKOUT_ROOT "\n");
133 fprintf(f, "please email this file to %s\n", crash_emailaddr);
134 std::string buffer = getLogBuffer();
135 fwrite(buffer.c_str(), buffer.size(), 1, f);
139 sprintf(cmd, "find /usr/lib/enigma2/python/ -name \"*.py\" | xargs md5sum >> %s", logfile);
145 gSDLDC::getInstance(my_dc);
148 gFBDC::getInstance(my_dc);
154 p.resetClip(eRect(ePoint(0, 0), my_dc->size()));
155 #ifdef ENIGMA2_CHECKOUT_TAG
156 if (ENIGMA2_CHECKOUT_TAG[0] == 'T') /* tagged checkout (release) */
157 p.setBackgroundColor(gRGB(0x0000C0));
158 else if (ENIGMA2_CHECKOUT_TAG[0] == 'D') /* dated checkout (daily experimental build) */
162 unsigned int col = 0;
169 p.setBackgroundColor(gRGB(col));
172 p.setBackgroundColor(gRGB(0x008000));
175 p.setForegroundColor(gRGB(0xFFFFFF));
177 ePtr<gFont> font = new gFont("Regular", 20);
181 eRect usable_area = eRect(100, 70, my_dc->size().width() - 150, 100);
184 snprintf(text, 512, "We are really sorry. Your Dreambox encountered "
185 "a software problem, and needs to be restarted. "
186 "Please send the logfile created in /hdd/ to %s.\n"
187 "Your Dreambox restarts in 10 seconds!\n"
189 crash_emailaddr, crash_component);
191 p.renderText(usable_area, text, gPainter::RT_WRAP|gPainter::RT_HALIGN_LEFT);
193 usable_area = eRect(100, 170, my_dc->size().width() - 180, my_dc->size().height() - 20);
197 size_t start = std::string::npos + 1;
200 start = lines.rfind('\n', start - 1);
201 if (start == std::string::npos)
208 font = new gFont("Regular", 14);
211 p.renderText(usable_area,
212 lines.substr(start), gPainter::RT_HALIGN_LEFT);
219 #if defined(__MIPSEL__)
220 void oops(const mcontext_t &context, int dumpcode)
222 eDebug("PC: %08lx", (unsigned long)context.pc);
226 eDebugNoNewLine(" %08x", (int)context.gregs[i]);
230 /* this is temporary debug stuff. */
231 if (dumpcode && ((unsigned long)context.pc) > 0x10000) /* not a zero pointer */
233 eDebug("As a final action, i will try to dump a bit of code.");
234 eDebug("I just hope that this won't crash.");
236 eDebugNoNewLine("%08lx:", (unsigned long)context.pc);
237 for (i=0; i<0x20; ++i)
238 eDebugNoNewLine(" %02x", ((unsigned char*)context.pc)[i]);
243 #warning "no oops support!"
244 #define NO_OOPS_SUPPORT
247 void handleFatalSignal(int signum, siginfo_t *si, void *ctx)
249 ucontext_t *uc = (ucontext_t*)ctx;
250 eDebug("KILLED BY signal %d", signum);
251 #ifndef NO_OOPS_SUPPORT
252 oops(uc->uc_mcontext, signum == SIGSEGV || signum == SIGABRT);
255 bsodFatal("enigma2, signal");
258 void bsodCatchSignals()
260 struct sigaction act;
261 act.sa_handler = SIG_DFL;
262 act.sa_sigaction = handleFatalSignal;
263 act.sa_flags = SA_RESTART | SA_SIGINFO;
264 if (sigemptyset(&act.sa_mask) == -1)
265 perror("sigemptyset");
267 /* start handling segfaults etc. */
268 sigaction(SIGSEGV, &act, 0);
269 sigaction(SIGILL, &act, 0);
270 sigaction(SIGBUS, &act, 0);
271 sigaction(SIGABRT, &act, 0);
276 logOutput.connect(addToLogbuffer);