summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPixel <pixel@nobis-crew.org>2011-11-21 13:27:53 -0800
committerPixel <pixel@nobis-crew.org>2011-11-21 13:27:53 -0800
commite10639753d7dbd368f5edc2555d75c4b5905ba3b (patch)
tree34b6c4bc2990f48de30d26486426558d643e7ac8 /src
parent071e7f07901309a38c8cb5311aaecaa46c0c3542 (diff)
GeneralException() will now trace the callstack and store this, for debugging purposes.
Diffstat (limited to 'src')
-rw-r--r--src/Exceptions.cc81
-rw-r--r--src/HttpServer.cc10
-rw-r--r--src/Task.cc3
3 files changed, 91 insertions, 3 deletions
diff --git a/src/Exceptions.cc b/src/Exceptions.cc
new file mode 100644
index 0000000..94de408
--- /dev/null
+++ b/src/Exceptions.cc
@@ -0,0 +1,81 @@
+#include "Exceptions.h"
+
+#define MAXTRACE 128
+
+#ifdef _WIN32
+
+#include <windows.h>
+
+void Balau::GeneralException::genTrace() {
+ // taken from http://stackoverflow.com/questions/5693192/win32-backtrace-from-c-code
+ unsigned int i;
+ void * stack[MAXTRACE];
+ unsigned short frames;
+ SYMBOL_INFO * symbol;
+ HANDLE process;
+
+ process = GetCurrentProcess();
+
+ SymInitialize(process, NULL, TRUE);
+
+ frames = CaptureStackBackTrace(0, MAXTRACE, stack, NULL);
+ symbol = (SYMBOL_INFO *) calloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char), 1);
+ symbol->MaxNameLen = 255;
+ symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
+
+ for (i = 0; i < frames; i++) {
+ SymFromAddr(process, (DWORD64)(stack[i]), 0, symbol);
+
+ int status;
+ String line;
+ char * demangled = abi::__cxa_demangle(symbol->Name, 0, 0, &status);
+ line.set("%i: 0x%08x (%s)", i, symbol->Address, status == 0 ? demangled : symbol->Name);
+ free(demangled);
+ m_trace.push_back(line);
+ }
+
+ free(symbol);
+}
+
+#else
+
+#include <execinfo.h>
+#include <dlfcn.h>
+
+void Balau::GeneralException::genTrace() {
+ void * trace[MAXTRACE];
+ int n = backtrace(trace, MAXTRACE);
+ char ** symbols = backtrace_symbols(trace, MAXTRACE);
+
+ if (!symbols)
+ return;
+
+ String line;
+ for (int i = 0; i < n; i++)
+ line += String().set("%08x ", trace[i]);
+
+ m_trace.push_back(line);
+ Dl_info info;
+
+ for (int i = 0; i < n; i++) {
+ int status;
+ String line;
+ dladdr(trace[i], &info);
+ long dist = ((char *) trace[i]) - ((char *) info.dli_saddr);
+ char * demangled;
+ if (info.dli_sname) {
+ demangled = abi::__cxa_demangle(info.dli_sname, 0, 0, &status);
+ } else {
+ demangled = NULL;
+ }
+ line.set("%i: %s(%s%c0x%x) [0x%08x]", i, info.dli_fname, info.dli_sname ? (demangled ? (status == 0 ? demangled : info.dli_sname) : info.dli_sname) : "??", dist < 0 ? '-' : '+', dist < 0 ? -dist : dist, trace[i]);
+ m_trace.push_back(line);
+ if (demangled)
+ free(demangled);
+ }
+
+ free(symbols);
+}
+
+
+#endif
diff --git a/src/HttpServer.cc b/src/HttpServer.cc
index 18dc6c8..7df6406 100644
--- a/src/HttpServer.cc
+++ b/src/HttpServer.cc
@@ -7,6 +7,7 @@ class OutputCheck : public Balau::Handle {
public:
OutputCheck(Balau::IO<Balau::Handle> h) : m_h(h), m_wrote(false) { Assert(m_h->canWrite()); m_name.set("OutputCheck(%s)", m_h->getName()); }
virtual void close() throw (Balau::GeneralException) { m_h->close(); }
+ virtual bool isClosed() { return m_h->isClosed(); }
virtual bool isEOF() { return m_h->isEOF(); }
virtual bool canWrite() { return true; }
virtual const char * getName() { return m_name.to_charp(); }
@@ -429,7 +430,7 @@ bool Balau::HttpWorker::handleClient() {
HttpServer::ActionFound f = m_server->findAction(uri.to_charp(), host.to_charp());
if (f.first) {
- IO<OutputCheck> out(m_socket);
+ IO<OutputCheck> out(new OutputCheck(m_socket));
Http::Request req;
req.method = method;
req.host = host;
@@ -443,13 +444,16 @@ bool Balau::HttpWorker::handleClient() {
persistent = false;
}
catch (GeneralException e) {
- Balau::Printer::elog(Balau::E_HTTPSERVER, "%s got an exception while processing its request: `%s'", m_name.to_charp(), e.getMsg());
+ Printer::log(M_ERROR, "%s got an exception while processing its request: `%s'", m_name.to_charp(), e.getMsg());
+ std::vector<String> trace = e.getTrace();
+ for (std::vector<String>::iterator i = trace.begin(); i != trace.end(); i++)
+ Printer::log(M_DEBUG, "%s", i->to_charp());
if (!out->wrote())
send500(e.getMsg());
return false;
}
catch (...) {
- Balau::Printer::elog(Balau::E_HTTPSERVER, "%s got an un unknow exception while processing its request: `%s'", m_name.to_charp());
+ Printer::log(M_ERROR, "%s got an unknow exception while processing its request: `%s'", m_name.to_charp());
if (!out->wrote())
send500("unknow exception");
return false;
diff --git a/src/Task.cc b/src/Task.cc
index 6a94267..5623698 100644
--- a/src/Task.cc
+++ b/src/Task.cc
@@ -61,6 +61,9 @@ void Balau::Task::coroutine() {
}
catch (GeneralException & e) {
Printer::log(M_WARNING, "Task %s at %p caused an exception: `%s' - stopping.", getName(), this, e.getMsg());
+ std::vector<String> trace = e.getTrace();
+ for (std::vector<String>::iterator i = trace.begin(); i != trace.end(); i++)
+ Printer::log(M_DEBUG, "%s", i->to_charp());
m_status = FAULTED;
}
catch (...) {