Add basic stacktrace handler using libunwind.
This means we will all have to apt-get install libunwind8-dev on Linux. Mac comes with everything we need already. BUG=skia: R=reed@google.com, mtklein@google.com Author: mtklein@chromium.org Review URL: https://codereview.chromium.org/343583005
This commit is contained in:
parent
f01a6c3663
commit
30e6e2af14
@ -6,6 +6,7 @@
|
||||
*/
|
||||
|
||||
#include "BenchTimer.h"
|
||||
#include "CrashHandler.h"
|
||||
#include "ResultsWriter.h"
|
||||
#include "SkBenchLogger.h"
|
||||
#include "SkBenchmark.h"
|
||||
@ -271,6 +272,7 @@ static bool HasConverged(double prevPerLoop, double currPerLoop, double currRaw)
|
||||
|
||||
int tool_main(int argc, char** argv);
|
||||
int tool_main(int argc, char** argv) {
|
||||
SetupCrashHandler();
|
||||
SkCommandLineFlags::Parse(argc, argv);
|
||||
#if SK_ENABLE_INST_COUNT
|
||||
if (FLAGS_leaks) {
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "SkString.h"
|
||||
#include "Test.h"
|
||||
#include "gm.h"
|
||||
#include "CrashHandler.h"
|
||||
|
||||
#include "DMBenchTask.h"
|
||||
#include "DMCpuGMTask.h"
|
||||
@ -215,6 +216,7 @@ static void append_matching_factories(Registry* head, SkTDArray<typename Registr
|
||||
|
||||
int tool_main(int argc, char** argv);
|
||||
int tool_main(int argc, char** argv) {
|
||||
SetupCrashHandler();
|
||||
SkAutoGraphics ag;
|
||||
SkCommandLineFlags::Parse(argc, argv);
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "gm_error.h"
|
||||
#include "gm_expectations.h"
|
||||
#include "system_preferences.h"
|
||||
#include "CrashHandler.h"
|
||||
#include "SkBitmap.h"
|
||||
#include "SkColorPriv.h"
|
||||
#include "SkCommandLineFlags.h"
|
||||
@ -2219,6 +2220,7 @@ static bool parse_flags_jpeg_quality() {
|
||||
|
||||
int tool_main(int argc, char** argv);
|
||||
int tool_main(int argc, char** argv) {
|
||||
SetupCrashHandler();
|
||||
|
||||
SkString usage;
|
||||
usage.printf("Run the golden master tests.\n");
|
||||
|
@ -9,11 +9,12 @@
|
||||
'target_name': 'bench',
|
||||
'type': 'executable',
|
||||
'dependencies': [
|
||||
'skia_lib.gyp:skia_lib',
|
||||
'bench_timer',
|
||||
'crash_handler.gyp:CrashHandler',
|
||||
'etc1.gyp:libetc1',
|
||||
'flags.gyp:flags',
|
||||
'jsoncpp.gyp:jsoncpp',
|
||||
'etc1.gyp:libetc1',
|
||||
'skia_lib.gyp:skia_lib',
|
||||
],
|
||||
'sources': [
|
||||
'../bench/ResultsWriter.cpp',
|
||||
|
11
gyp/crash_handler.gyp
Normal file
11
gyp/crash_handler.gyp
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
'targets': [{
|
||||
'target_name': 'CrashHandler',
|
||||
'type': 'static_library',
|
||||
'sources': [ '../tools/CrashHandler.cpp' ],
|
||||
'dependencies': [ 'skia_lib.gyp:skia_lib' ],
|
||||
'direct_dependent_settings': {
|
||||
'include_dirs': [ '../tools' ],
|
||||
},
|
||||
}]
|
||||
}
|
@ -55,11 +55,12 @@
|
||||
'../src/utils/debugger/SkObjectParser.cpp',
|
||||
],
|
||||
'dependencies': [
|
||||
'skia_lib.gyp:skia_lib',
|
||||
'flags.gyp:flags',
|
||||
'jsoncpp.gyp:jsoncpp',
|
||||
'gputest.gyp:skgputest',
|
||||
'crash_handler.gyp:CrashHandler',
|
||||
'etc1.gyp:libetc1',
|
||||
'flags.gyp:flags',
|
||||
'gputest.gyp:skgputest',
|
||||
'jsoncpp.gyp:jsoncpp',
|
||||
'skia_lib.gyp:skia_lib',
|
||||
],
|
||||
'conditions': [
|
||||
['skia_android_framework', {
|
||||
|
@ -16,8 +16,9 @@
|
||||
'../tools/sk_tool_utils.cpp',
|
||||
],
|
||||
'dependencies': [
|
||||
'skia_lib.gyp:skia_lib',
|
||||
'crash_handler.gyp:CrashHandler',
|
||||
'jsoncpp.gyp:jsoncpp',
|
||||
'skia_lib.gyp:skia_lib',
|
||||
],
|
||||
'direct_dependent_settings': {
|
||||
'include_dirs': [
|
||||
|
@ -11,6 +11,7 @@
|
||||
'pathops_unittest.gypi',
|
||||
'tests.gypi',
|
||||
],
|
||||
'dependencies': [ 'crash_handler.gyp:CrashHandler' ],
|
||||
'sources': [
|
||||
'../tests/skia_test.cpp',
|
||||
],
|
||||
|
@ -300,11 +300,12 @@
|
||||
],
|
||||
'dependencies': [
|
||||
'bench.gyp:bench_timer',
|
||||
'crash_handler.gyp:CrashHandler',
|
||||
'flags.gyp:flags',
|
||||
'jsoncpp.gyp:jsoncpp',
|
||||
'skia_lib.gyp:skia_lib',
|
||||
'tools.gyp:picture_utils',
|
||||
'tools.gyp:picture_renderer',
|
||||
'tools.gyp:picture_utils',
|
||||
'tools.gyp:timer_data',
|
||||
],
|
||||
},
|
||||
|
@ -5,6 +5,7 @@
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "CrashHandler.h"
|
||||
#include "OverwriteLine.h"
|
||||
#include "SkCommandLineFlags.h"
|
||||
#include "SkGraphics.h"
|
||||
@ -132,6 +133,7 @@ static bool should_run(const char* testName, bool isGPUTest) {
|
||||
|
||||
int tool_main(int argc, char** argv);
|
||||
int tool_main(int argc, char** argv) {
|
||||
SetupCrashHandler();
|
||||
SkCommandLineFlags::SetUsage("");
|
||||
SkCommandLineFlags::Parse(argc, argv);
|
||||
Test::SetResourcePath(FLAGS_resourcePath[0]);
|
||||
|
88
tools/CrashHandler.cpp
Normal file
88
tools/CrashHandler.cpp
Normal file
@ -0,0 +1,88 @@
|
||||
#include "CrashHandler.h"
|
||||
|
||||
#include "SkTypes.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
|
||||
#if defined(SK_BUILD_FOR_MAC)
|
||||
|
||||
// We only use local unwinding, so we can define this to select a faster implementation.
|
||||
#define UNW_LOCAL_ONLY
|
||||
#include <libunwind.h>
|
||||
#include <cxxabi.h>
|
||||
|
||||
static void handler(int sig) {
|
||||
unw_context_t context;
|
||||
unw_getcontext(&context);
|
||||
|
||||
unw_cursor_t cursor;
|
||||
unw_init_local(&cursor, &context);
|
||||
|
||||
fprintf(stderr, "\nSignal %d:\n", sig);
|
||||
while (unw_step(&cursor) > 0) {
|
||||
static const size_t kMax = 256;
|
||||
char mangled[kMax], demangled[kMax];
|
||||
unw_word_t offset;
|
||||
unw_get_proc_name(&cursor, mangled, kMax, &offset);
|
||||
|
||||
int ok;
|
||||
size_t len = kMax;
|
||||
abi::__cxa_demangle(mangled, demangled, &len, &ok);
|
||||
|
||||
fprintf(stderr, "%s (+0x%zx)\n", ok == 0 ? demangled : mangled, (size_t)offset);
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
// Exit NOW. Don't notify other threads, don't call anything registered with atexit().
|
||||
_Exit(sig);
|
||||
}
|
||||
|
||||
#elif defined(SK_BUILD_FOR_UNIX)
|
||||
|
||||
// We'd use libunwind here too, but it's a pain to get installed for both 32 and 64 bit on bots.
|
||||
// Doesn't matter much: catchsegv is best anyway.
|
||||
#include <execinfo.h>
|
||||
|
||||
static void handler(int sig) {
|
||||
static const int kMax = 64;
|
||||
void* stack[kMax];
|
||||
const int count = backtrace(stack, kMax);
|
||||
|
||||
fprintf(stderr, "\nSignal %d:\n", sig);
|
||||
backtrace_symbols_fd(stack, count, 2/*stderr*/);
|
||||
|
||||
// Exit NOW. Don't notify other threads, don't call anything registered with atexit().
|
||||
_Exit(sig);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(SK_BUILD_FOR_UNIX) || defined(SK_BUILD_FOR_MAC)
|
||||
|
||||
void SetupCrashHandler() {
|
||||
static const int kSignals[] = {
|
||||
SIGABRT,
|
||||
SIGBUS,
|
||||
SIGFPE,
|
||||
SIGILL,
|
||||
SIGSEGV,
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < sizeof(kSignals) / sizeof(kSignals[0]); i++) {
|
||||
// Register our signal handler unless something's already done so (e.g. catchsegv).
|
||||
void (*prev)(int) = signal(kSignals[i], handler);
|
||||
if (prev != SIG_DFL) {
|
||||
signal(kSignals[i], prev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: #elif defined(SK_BUILD_FOR_WIN) when I find a Windows machine to work from.
|
||||
|
||||
#else
|
||||
|
||||
void SetupCrashHandler() { }
|
||||
|
||||
#endif
|
9
tools/CrashHandler.h
Normal file
9
tools/CrashHandler.h
Normal file
@ -0,0 +1,9 @@
|
||||
#ifndef CrashHandler_DEFINED
|
||||
#define CrashHandler_DEFINED
|
||||
|
||||
// If possible (and not already done) register a handler for a stack trace when we crash.
|
||||
// Currently this works on Linux and Mac, hopefully Windows soon.
|
||||
// On Linux, you will get much better results than we can deliver by running "catchsegv <program>".
|
||||
void SetupCrashHandler();
|
||||
|
||||
#endif//CrashHandler_DEFINED
|
@ -6,6 +6,7 @@
|
||||
*/
|
||||
|
||||
#include "BenchTimer.h"
|
||||
#include "CrashHandler.h"
|
||||
#include "CopyTilesRenderer.h"
|
||||
#include "LazyDecodeBitmap.h"
|
||||
#include "PictureBenchmark.h"
|
||||
@ -391,6 +392,7 @@ static int process_input(const char* input,
|
||||
|
||||
int tool_main(int argc, char** argv);
|
||||
int tool_main(int argc, char** argv) {
|
||||
SetupCrashHandler();
|
||||
SkString usage;
|
||||
usage.printf("Time drawing .skp files.\n"
|
||||
"\tPossible arguments for --filter: [%s]\n\t\t[%s]",
|
||||
|
Loading…
Reference in New Issue
Block a user