Skip to content

Commit

Permalink
Print out stack trace in mac, too
Browse files Browse the repository at this point in the history
Summary: While debugging Mac-only issue with ThreadLocalPtr, this was very useful. Let's print out stack trace in MAC OS, too.

Test Plan: Verified that somewhat useful stack trace was generated on mac. Will run PrintStack() on linux, too.

Reviewers: ljin, haobo

Reviewed By: haobo

CC: leveldb

Differential Revision: https://reviews.facebook.net/D18189
  • Loading branch information
igorcanadi committed Apr 23, 2014
1 parent a570740 commit f9f8965
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 48 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ build_config.mk
*.jar
*.*jnilib*
*.d-e
*.o-*

ldb
manifest_dump
Expand Down
4 changes: 2 additions & 2 deletions db/db_bench.cc
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@
#include "rocksdb/statistics.h"
#include "rocksdb/perf_context.h"
#include "port/port.h"
#include "port/stack_trace.h"
#include "util/crc32c.h"
#include "util/histogram.h"
#include "util/mutexlock.h"
#include "util/random.h"
#include "util/stack_trace.h"
#include "util/string_util.h"
#include "util/statistics.h"
#include "util/testutil.h"
Expand Down Expand Up @@ -2528,7 +2528,7 @@ class Benchmark {
} // namespace rocksdb

int main(int argc, char** argv) {
rocksdb::InstallStackTraceHandler();
rocksdb::port::InstallStackTraceHandler();
google::SetUsageMessage(std::string("\nUSAGE:\n") + std::string(argv[0]) +
" [OPTIONS]...");
google::ParseCommandLineFlags(&argc, &argv, true);
Expand Down
101 changes: 60 additions & 41 deletions port/stack_trace.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,19 @@
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
//
#include "util/stack_trace.h"
#include "port/stack_trace.h"

#ifdef OS_LINUX
namespace rocksdb {
namespace port {

#if defined(ROCKSDB_LITE) || !(defined(OS_LINUX) || defined(OS_MACOSX))

// noop

void InstallStackTraceHandler() {}
void PrintStack(int first_frames_to_skip) {}

#else

#include <execinfo.h>
#include <signal.h>
Expand All @@ -14,10 +24,10 @@
#include <string.h>
#include <unistd.h>

namespace rocksdb {
namespace {

static const char* GetExecutableName()
{
#ifdef OS_LINUX
const char* GetExecutableName() {
static char name[1024];

char link[1024];
Expand All @@ -31,38 +41,56 @@ static const char* GetExecutableName()
}
}

void PrintStackTraceLine(const char* symbol, void* frame) {
static const char* executable = GetExecutableName();
if (symbol) {
fprintf(stderr, "%s ", symbol);
}
if (executable) {
// out source to addr2line, for the address translation
const int kLineMax = 256;
char cmd[kLineMax];
snprintf(cmd, kLineMax, "addr2line %p -e %s -f -C 2>&1", frame, executable);
auto f = popen(cmd, "r");
if (f) {
char line[kLineMax];
while (fgets(line, sizeof(line), f)) {
line[strlen(line) - 1] = 0; // remove newline
fprintf(stderr, "%s\t", line);
}
pclose(f);
}
} else {
fprintf(stderr, " %p", frame);
}

fprintf(stderr, "\n");
}
#elif OS_MACOSX

void PrintStackTraceLine(const char* symbol, void* frame) {
// TODO(icanadi) demangle
if (symbol) {
fprintf(stderr, "%s ", symbol);
}
fprintf(stderr, " %p", frame);
fprintf(stderr, "\n");
}

#endif

} // namespace

void PrintStack(int first_frames_to_skip) {
const int kMaxFrames = 100;
void *frames[kMaxFrames];
void* frames[kMaxFrames];

auto num_frames = backtrace(frames, kMaxFrames);
auto symbols = backtrace_symbols(frames, num_frames);

auto executable = GetExecutableName();

for (int i = first_frames_to_skip; i < num_frames; ++i) {
fprintf(stderr, "#%-2d ", i - first_frames_to_skip);
if (symbols) {
fprintf(stderr, "%s ", symbols[i]);
}
if (executable) {
// out source to addr2line, for the address translation
const int kLineMax = 256;
char cmd[kLineMax];
sprintf(cmd, "addr2line %p -e %s -f -C 2>&1", frames[i], executable);
auto f = popen(cmd, "r");
if (f) {
char line[kLineMax];
while (fgets(line, sizeof(line), f)) {
line[strlen(line) - 1] = 0; // remove newline
fprintf(stderr, "%s\t", line);
}
pclose(f);
}
} else {
fprintf(stderr, " %p", frames[i]);
}
fprintf(stderr, "\n");
PrintStackTraceLine((symbols != nullptr) ? symbols[i] : nullptr, frames[i]);
}
}

Expand All @@ -85,18 +113,9 @@ void InstallStackTraceHandler() {
signal(SIGABRT, StackTraceHandler);

printf("Installed stack trace handler for SIGILL SIGSEGV SIGBUS SIGABRT\n");

}

} // namespace rocksdb

#else // no-op for non-linux system for now

namespace rocksdb {

void InstallStackTraceHandler() {}
void PrintStack(int first_frames_to_skip) {}

}
#endif

#endif // OS_LINUX
} // namespace port
} // namespace rocksdb
4 changes: 3 additions & 1 deletion util/stack_trace.h → port/stack_trace.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
//
#pragma once
namespace rocksdb {
namespace port {

// Install a signal handler to print callstack on the following signals:
// SIGILL SIGSEGV SIGBUS SIGABRT
Expand All @@ -14,4 +15,5 @@ void InstallStackTraceHandler();
// Prints stack, skips skip_first_frames frames
void PrintStack(int first_frames_to_skip = 0);

} // namespace rocksdb
} // namespace port
} // namespace rocksdb
4 changes: 2 additions & 2 deletions util/signal_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
//
#include "util/stack_trace.h"
#include "port/stack_trace.h"
#include <assert.h>

namespace {
Expand All @@ -26,7 +26,7 @@ void f3() {
} // namespace

int main() {
rocksdb::InstallStackTraceHandler();
rocksdb::port::InstallStackTraceHandler();

f3();

Expand Down
4 changes: 2 additions & 2 deletions util/testharness.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@
#include <stdio.h>
#include <stdlib.h>
#include <sstream>
#include "port/stack_trace.h"
#include "rocksdb/env.h"
#include "rocksdb/slice.h"
#include "util/random.h"
#include "util/stack_trace.h"

namespace rocksdb {
namespace test {
Expand Down Expand Up @@ -59,7 +59,7 @@ class Tester {
~Tester() {
if (!ok_) {
fprintf(stderr, "%s:%d:%s\n", fname_, line_, ss_.str().c_str());
PrintStack(2);
port::PrintStack(2);
exit(1);
}
}
Expand Down

0 comments on commit f9f8965

Please sign in to comment.