| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "CrashHandler.h" | 8 #include "CrashHandler.h" |
| 9 #include "DMJsonWriter.h" | 9 #include "DMJsonWriter.h" |
| 10 #include "DMSrcSink.h" | 10 #include "DMSrcSink.h" |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 157 SkString elapsed = HumanizeMs(SkTime::GetMSecs() - kStartMs); | 157 SkString elapsed = HumanizeMs(SkTime::GetMSecs() - kStartMs); |
| 158 | 158 |
| 159 SkAutoTAcquire<SkSpinlock> lock(gMutex); | 159 SkAutoTAcquire<SkSpinlock> lock(gMutex); |
| 160 info("\n%s elapsed, %d active, %d queued, %dMB RAM, %dMB peak\n", | 160 info("\n%s elapsed, %d active, %d queued, %dMB RAM, %dMB peak\n", |
| 161 elapsed.c_str(), gRunning.count(), gPending - gRunning.count(), curr, p
eak); | 161 elapsed.c_str(), gRunning.count(), gPending - gRunning.count(), curr, p
eak); |
| 162 for (auto& task : gRunning) { | 162 for (auto& task : gRunning) { |
| 163 info("\t%s\n", task.c_str()); | 163 info("\t%s\n", task.c_str()); |
| 164 } | 164 } |
| 165 } | 165 } |
| 166 | 166 |
| 167 // Yo dawg, I heard you like signals so I caught a signal in your | |
| 168 // signal handler so you can handle signals while you handle signals. | |
| 169 // Let's not get into that situation. Only print if we're the first ones to get
a crash signal. | |
| 170 static std::atomic<bool> in_signal_handler{false}; | |
| 171 | |
| 172 #if defined(SK_BUILD_FOR_WIN32) | 167 #if defined(SK_BUILD_FOR_WIN32) |
| 173 static LONG WINAPI handler(EXCEPTION_POINTERS* e) { | 168 static LONG WINAPI crash_handler(EXCEPTION_POINTERS* e) { |
| 174 static const struct { | 169 static const struct { |
| 175 const char* name; | 170 const char* name; |
| 176 DWORD code; | 171 DWORD code; |
| 177 } kExceptions[] = { | 172 } kExceptions[] = { |
| 178 #define _(E) {#E, E} | 173 #define _(E) {#E, E} |
| 179 _(EXCEPTION_ACCESS_VIOLATION), | 174 _(EXCEPTION_ACCESS_VIOLATION), |
| 180 _(EXCEPTION_BREAKPOINT), | 175 _(EXCEPTION_BREAKPOINT), |
| 181 _(EXCEPTION_INT_DIVIDE_BY_ZERO), | 176 _(EXCEPTION_INT_DIVIDE_BY_ZERO), |
| 182 _(EXCEPTION_STACK_OVERFLOW), | 177 _(EXCEPTION_STACK_OVERFLOW), |
| 183 // TODO: more? | 178 // TODO: more? |
| 184 #undef _ | 179 #undef _ |
| 185 }; | 180 }; |
| 186 | 181 |
| 187 if (!in_signal_handler.exchange(true)) { | 182 SkAutoTAcquire<SkSpinlock> lock(gMutex); |
| 188 const DWORD code = e->ExceptionRecord->ExceptionCode; | 183 |
| 189 info("\nCaught exception %u", code); | 184 const DWORD code = e->ExceptionRecord->ExceptionCode; |
| 190 for (const auto& exception : kExceptions) { | 185 info("\nCaught exception %u", code); |
| 191 if (exception.code == code) { | 186 for (const auto& exception : kExceptions) { |
| 192 info(" %s", exception.name); | 187 if (exception.code == code) { |
| 193 } | 188 info(" %s", exception.name); |
| 194 } | 189 } |
| 195 info("\n"); | |
| 196 print_status(); | |
| 197 fflush(stdout); | |
| 198 } | 190 } |
| 191 info(", was running:\n"); |
| 192 for (auto& task : gRunning) { |
| 193 info("\t%s\n", task.c_str()); |
| 194 } |
| 195 fflush(stdout); |
| 196 |
| 199 // Execute default exception handler... hopefully, exit. | 197 // Execute default exception handler... hopefully, exit. |
| 200 return EXCEPTION_EXECUTE_HANDLER; | 198 return EXCEPTION_EXECUTE_HANDLER; |
| 201 } | 199 } |
| 202 static void setup_crash_handler() { SetUnhandledExceptionFilter(handler); } | 200 static void setup_crash_handler() { SetUnhandledExceptionFilter(crash_handle
r); } |
| 203 | 201 |
| 204 #elif !defined(SK_BUILD_FOR_ANDROID) | 202 #elif !defined(SK_BUILD_FOR_ANDROID) |
| 205 #include <execinfo.h> | 203 #include <execinfo.h> |
| 206 #include <signal.h> | 204 #include <signal.h> |
| 207 #include <stdlib.h> | 205 #include <stdlib.h> |
| 208 | 206 |
| 207 static void crash_handler(int sig) { |
| 208 SkAutoTAcquire<SkSpinlock> lock(gMutex); |
| 209 |
| 210 info("\nCaught signal %d [%s], was running:\n", sig, strsignal(sig)); |
| 211 for (auto& task : gRunning) { |
| 212 info("\t%s\n", task.c_str()); |
| 213 } |
| 214 |
| 215 void* stack[64]; |
| 216 int count = backtrace(stack, SK_ARRAY_COUNT(stack)); |
| 217 char** symbols = backtrace_symbols(stack, count); |
| 218 info("\nStack trace:\n"); |
| 219 for (int i = 0; i < count; i++) { |
| 220 info(" %s\n", symbols[i]); |
| 221 } |
| 222 fflush(stdout); |
| 223 |
| 224 _Exit(sig); |
| 225 } |
| 226 |
| 209 static void setup_crash_handler() { | 227 static void setup_crash_handler() { |
| 210 const int kSignals[] = { SIGABRT, SIGBUS, SIGFPE, SIGILL, SIGSEGV }; | 228 const int kSignals[] = { SIGABRT, SIGBUS, SIGFPE, SIGILL, SIGSEGV }; |
| 211 for (int sig : kSignals) { | 229 for (int sig : kSignals) { |
| 212 signal(sig, [](int sig) { | 230 signal(sig, crash_handler); |
| 213 if (!in_signal_handler.exchange(true)) { | |
| 214 SkAutoTAcquire<SkSpinlock> lock(gMutex); | |
| 215 info("\nCaught signal %d [%s], was running:\n", sig, strsign
al(sig)); | |
| 216 for (auto& task : gRunning) { | |
| 217 info("\t%s\n", task.c_str()); | |
| 218 } | |
| 219 | |
| 220 void* stack[64]; | |
| 221 int count = backtrace(stack, SK_ARRAY_COUNT(stack)); | |
| 222 char** symbols = backtrace_symbols(stack, count); | |
| 223 info("\nStack trace:\n"); | |
| 224 for (int i = 0; i < count; i++) { | |
| 225 info(" %s\n", symbols[i]); | |
| 226 } | |
| 227 fflush(stdout); | |
| 228 } | |
| 229 _Exit(sig); | |
| 230 }); | |
| 231 } | 231 } |
| 232 } | 232 } |
| 233 | 233 |
| 234 #else // Android | 234 #else // Android |
| 235 static void setup_crash_handler() {} | 235 static void setup_crash_handler() {} |
| 236 #endif | 236 #endif |
| 237 | 237 |
| 238 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~*/ | 238 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~*/ |
| 239 | 239 |
| 240 struct Gold : public SkString { | 240 struct Gold : public SkString { |
| (...skipping 1163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1404 #endif | 1404 #endif |
| 1405 } | 1405 } |
| 1406 } // namespace skiatest | 1406 } // namespace skiatest |
| 1407 | 1407 |
| 1408 #if !defined(SK_BUILD_FOR_IOS) | 1408 #if !defined(SK_BUILD_FOR_IOS) |
| 1409 int main(int argc, char** argv) { | 1409 int main(int argc, char** argv) { |
| 1410 SkCommandLineFlags::Parse(argc, argv); | 1410 SkCommandLineFlags::Parse(argc, argv); |
| 1411 return dm_main(); | 1411 return dm_main(); |
| 1412 } | 1412 } |
| 1413 #endif | 1413 #endif |
| OLD | NEW |