add backtracer
authorEvan Martin <martine@danga.com>
Tue, 30 Nov 2010 18:38:52 +0000 (10:38 -0800)
committerEvan Martin <martine@danga.com>
Tue, 30 Nov 2010 18:38:52 +0000 (10:38 -0800)
build.ninja
subprocess.cc
subprocess.h
util.cc [new file with mode: 0644]
util.h [new file with mode: 0644]

index 2314daf..3998cbe 100644 (file)
@@ -11,6 +11,8 @@ builddir = build
 cxx = g++
 #cxx = /home/evanm/projects/src/llvm/Release+Asserts/bin/clang++
 cflags = -g -Wall
+# needed for backtrace()
+ldflags = -g -rdynamic
 
 # Here we declare a "rule" named "cxx", which knows how to compile
 # C++ code.  The variables indented below the rule are scoped to the
@@ -32,8 +34,9 @@ rule link
 build @build.o: cxx build.cc
 build @parsers.o: cxx parsers.cc
 build @subprocess.o: cxx subprocess.cc
+build @util.o: cxx util.cc
 build @ninja_jumble.o: cxx ninja_jumble.cc
-build @ninja.a: ar @build.o @parsers.o @subprocess.o @ninja_jumble.o
+build @ninja.a: ar @build.o @parsers.o @subprocess.o @util.o @ninja_jumble.o
 
 build @ninja.o: cxx ninja.cc
 build ninja: link @ninja.o @ninja.a
@@ -44,7 +47,7 @@ build @parsers_test.o: cxx parsers_test.cc
 build @subprocess_test.o: cxx subprocess_test.cc
 build ninja_test: link @build_test.o @ninja_test.o @parsers_test.o \
       @subprocess_test.o @ninja.a
-  ldflags = -lgtest -lgtest_main -lpthread
+  ldflags = -g -rdynamic -lgtest -lgtest_main -lpthread
 
 
 # Generate a graph of the dependency tree (including the
index 0c93c4a..ece09e8 100644 (file)
@@ -10,6 +10,8 @@
 #include <string.h>
 #include <sys/wait.h>
 
+#include "util.h"
+
 Subprocess::Stream::Stream() : fd_(-1) {}
 Subprocess::Stream::~Stream() {
   if (fd_ >= 0)
@@ -67,7 +69,7 @@ void Subprocess::OnFDReady(int fd) {
     stream->buf_.append(buf, len);
   } else {
     if (len < 0)
-      err_ = strerror(errno);
+      Fatal("read: %s", strerror(errno));
     close(stream->fd_);
     stream->fd_ = -1;
   }
index 91f0771..a65b729 100644 (file)
@@ -26,7 +26,6 @@ struct Subprocess {
   };
   Stream stdout_, stderr_;
   pid_t pid_;
-  string err_;
 };
 
 // SubprocessSet runs a poll() loop around a set of Subprocesses.
diff --git a/util.cc b/util.cc
new file mode 100644 (file)
index 0000000..7a1c4e6
--- /dev/null
+++ b/util.cc
@@ -0,0 +1,24 @@
+#include "util.h"
+
+#include <execinfo.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+void DumpBacktrace(int skip_frames) {
+  void* stack[256];
+  int size = backtrace(stack, 256);
+  ++skip_frames;  // Skip ourselves as well.
+  backtrace_symbols_fd(stack + skip_frames, size - skip_frames, 2);
+}
+
+void Fatal(const char* msg, ...) {
+  va_list ap;
+  fprintf(stderr, "FATAL: ");
+  va_start(ap, msg);
+  vfprintf(stderr, msg, ap);
+  va_end(ap);
+  fprintf(stderr, "\n");
+  DumpBacktrace(1);
+  exit(1);
+}
diff --git a/util.h b/util.h
new file mode 100644 (file)
index 0000000..d0f0815
--- /dev/null
+++ b/util.h
@@ -0,0 +1,9 @@
+
+
+// Dump a backtrace to stderr.
+// |skip_frames| is how many frames to skip;
+// DumpBacktrace implicitly skips itself already.
+void DumpBacktrace(int skip_frames);
+
+// Log a fatal message, dump a backtrace, and exit.
+void Fatal(const char* msg, ...);