henrike@webrtc.org | f048872 | 2014-05-13 18:00:26 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2006 The WebRTC Project Authors. All rights reserved. |
| 3 | * |
| 4 | * Use of this source code is governed by a BSD-style license |
| 5 | * that can be found in the LICENSE file in the root of the source |
| 6 | * tree. An additional intellectual property rights grant can be found |
| 7 | * in the file PATENTS. All contributing project authors may |
| 8 | * be found in the AUTHORS file in the root of the source tree. |
| 9 | */ |
| 10 | |
andrew@webrtc.org | a5b7869 | 2014-08-28 16:28:26 +0000 | [diff] [blame] | 11 | // Most of this was borrowed (with minor modifications) from V8's and Chromium's |
| 12 | // src/base/logging.cc. |
| 13 | |
| 14 | // Use the C++ version to provide __GLIBCXX__. |
andrew@webrtc.org | 34a6764 | 2014-09-02 19:00:45 +0000 | [diff] [blame] | 15 | #include <cstdarg> |
andrew@webrtc.org | 4ca66d6 | 2014-09-10 03:24:36 +0000 | [diff] [blame] | 16 | #include <cstdio> |
| 17 | #include <cstdlib> |
andrew@webrtc.org | a5b7869 | 2014-08-28 16:28:26 +0000 | [diff] [blame] | 18 | |
| 19 | #if defined(__GLIBCXX__) && !defined(__UCLIBC__) |
| 20 | #include <cxxabi.h> |
| 21 | #include <execinfo.h> |
| 22 | #endif |
| 23 | |
andrew@webrtc.org | 34a6764 | 2014-09-02 19:00:45 +0000 | [diff] [blame] | 24 | #if defined(WEBRTC_ANDROID) |
Mirko Bonadei | 8ed8e56 | 2017-10-27 09:43:53 +0200 | [diff] [blame] | 25 | #define RTC_LOG_TAG_ANDROID "rtc" |
andrew@webrtc.org | a5b7869 | 2014-08-28 16:28:26 +0000 | [diff] [blame] | 26 | #include <android/log.h> // NOLINT |
| 27 | #endif |
| 28 | |
tommi | e8be6ff | 2016-04-22 01:22:24 -0700 | [diff] [blame] | 29 | #if defined(WEBRTC_WIN) |
| 30 | #include <windows.h> |
| 31 | #endif |
| 32 | |
Mirko Bonadei | 92ea95e | 2017-09-15 06:47:31 +0200 | [diff] [blame] | 33 | #include "rtc_base/checks.h" |
| 34 | #include "rtc_base/logging.h" |
henrike@webrtc.org | f048872 | 2014-05-13 18:00:26 +0000 | [diff] [blame] | 35 | |
andrew@webrtc.org | a5b7869 | 2014-08-28 16:28:26 +0000 | [diff] [blame] | 36 | #if defined(_MSC_VER) |
| 37 | // Warning C4722: destructor never returns, potential memory leak. |
| 38 | // FatalMessage's dtor very intentionally aborts. |
| 39 | #pragma warning(disable:4722) |
| 40 | #endif |
| 41 | |
henrike@webrtc.org | c50bf7c | 2014-05-14 18:24:13 +0000 | [diff] [blame] | 42 | namespace rtc { |
| 43 | |
andrew@webrtc.org | a5b7869 | 2014-08-28 16:28:26 +0000 | [diff] [blame] | 44 | void VPrintError(const char* format, va_list args) { |
| 45 | #if defined(WEBRTC_ANDROID) |
Mirko Bonadei | 8ed8e56 | 2017-10-27 09:43:53 +0200 | [diff] [blame] | 46 | __android_log_vprint(ANDROID_LOG_ERROR, RTC_LOG_TAG_ANDROID, format, args); |
andrew@webrtc.org | a5b7869 | 2014-08-28 16:28:26 +0000 | [diff] [blame] | 47 | #else |
| 48 | vfprintf(stderr, format, args); |
| 49 | #endif |
| 50 | } |
henrike@webrtc.org | f048872 | 2014-05-13 18:00:26 +0000 | [diff] [blame] | 51 | |
andrew@webrtc.org | a5b7869 | 2014-08-28 16:28:26 +0000 | [diff] [blame] | 52 | void PrintError(const char* format, ...) { |
| 53 | va_list args; |
| 54 | va_start(args, format); |
| 55 | VPrintError(format, args); |
| 56 | va_end(args); |
| 57 | } |
henrike@webrtc.org | f048872 | 2014-05-13 18:00:26 +0000 | [diff] [blame] | 58 | |
andrew@webrtc.org | a5b7869 | 2014-08-28 16:28:26 +0000 | [diff] [blame] | 59 | // TODO(ajm): This works on Mac (although the parsing fails) but I don't seem |
| 60 | // to get usable symbols on Linux. This is copied from V8. Chromium has a more |
| 61 | // advanced stace trace system; also more difficult to copy. |
| 62 | void DumpBacktrace() { |
| 63 | #if defined(__GLIBCXX__) && !defined(__UCLIBC__) |
| 64 | void* trace[100]; |
andrew@webrtc.org | 34a6764 | 2014-09-02 19:00:45 +0000 | [diff] [blame] | 65 | int size = backtrace(trace, sizeof(trace) / sizeof(*trace)); |
andrew@webrtc.org | a5b7869 | 2014-08-28 16:28:26 +0000 | [diff] [blame] | 66 | char** symbols = backtrace_symbols(trace, size); |
| 67 | PrintError("\n==== C stack trace ===============================\n\n"); |
| 68 | if (size == 0) { |
| 69 | PrintError("(empty)\n"); |
deadbeef | 37f5ecf | 2017-02-27 14:06:41 -0800 | [diff] [blame] | 70 | } else if (symbols == nullptr) { |
andrew@webrtc.org | a5b7869 | 2014-08-28 16:28:26 +0000 | [diff] [blame] | 71 | PrintError("(no symbols)\n"); |
| 72 | } else { |
| 73 | for (int i = 1; i < size; ++i) { |
| 74 | char mangled[201]; |
| 75 | if (sscanf(symbols[i], "%*[^(]%*[(]%200[^)+]", mangled) == 1) { // NOLINT |
| 76 | PrintError("%2d: ", i); |
| 77 | int status; |
| 78 | size_t length; |
deadbeef | 37f5ecf | 2017-02-27 14:06:41 -0800 | [diff] [blame] | 79 | char* demangled = |
| 80 | abi::__cxa_demangle(mangled, nullptr, &length, &status); |
| 81 | PrintError("%s\n", demangled != nullptr ? demangled : mangled); |
andrew@webrtc.org | a5b7869 | 2014-08-28 16:28:26 +0000 | [diff] [blame] | 82 | free(demangled); |
| 83 | } else { |
| 84 | // If parsing failed, at least print the unparsed symbol. |
| 85 | PrintError("%s\n", symbols[i]); |
| 86 | } |
| 87 | } |
| 88 | } |
| 89 | free(symbols); |
| 90 | #endif |
| 91 | } |
| 92 | |
| 93 | FatalMessage::FatalMessage(const char* file, int line) { |
| 94 | Init(file, line); |
| 95 | } |
| 96 | |
| 97 | FatalMessage::FatalMessage(const char* file, int line, std::string* result) { |
| 98 | Init(file, line); |
| 99 | stream_ << "Check failed: " << *result << std::endl << "# "; |
| 100 | delete result; |
| 101 | } |
| 102 | |
kjellander | bdf3072 | 2017-09-08 11:00:21 -0700 | [diff] [blame] | 103 | NO_RETURN FatalMessage::~FatalMessage() { |
andrew@webrtc.org | a5b7869 | 2014-08-28 16:28:26 +0000 | [diff] [blame] | 104 | fflush(stdout); |
| 105 | fflush(stderr); |
| 106 | stream_ << std::endl << "#" << std::endl; |
| 107 | PrintError(stream_.str().c_str()); |
| 108 | DumpBacktrace(); |
| 109 | fflush(stderr); |
henrike@webrtc.org | f048872 | 2014-05-13 18:00:26 +0000 | [diff] [blame] | 110 | abort(); |
| 111 | } |
henrike@webrtc.org | c50bf7c | 2014-05-14 18:24:13 +0000 | [diff] [blame] | 112 | |
andrew@webrtc.org | a5b7869 | 2014-08-28 16:28:26 +0000 | [diff] [blame] | 113 | void FatalMessage::Init(const char* file, int line) { |
tommi | e8be6ff | 2016-04-22 01:22:24 -0700 | [diff] [blame] | 114 | stream_ << std::endl << std::endl |
| 115 | << "#" << std::endl |
| 116 | << "# Fatal error in " << file << ", line " << line << std::endl |
| 117 | << "# last system error: " << LAST_SYSTEM_ERROR << std::endl |
| 118 | << "# "; |
andrew@webrtc.org | a5b7869 | 2014-08-28 16:28:26 +0000 | [diff] [blame] | 119 | } |
| 120 | |
| 121 | // MSVC doesn't like complex extern templates and DLLs. |
| 122 | #if !defined(COMPILER_MSVC) |
| 123 | // Explicit instantiations for commonly used comparisons. |
| 124 | template std::string* MakeCheckOpString<int, int>( |
| 125 | const int&, const int&, const char* names); |
| 126 | template std::string* MakeCheckOpString<unsigned long, unsigned long>( |
| 127 | const unsigned long&, const unsigned long&, const char* names); |
| 128 | template std::string* MakeCheckOpString<unsigned long, unsigned int>( |
| 129 | const unsigned long&, const unsigned int&, const char* names); |
| 130 | template std::string* MakeCheckOpString<unsigned int, unsigned long>( |
| 131 | const unsigned int&, const unsigned long&, const char* names); |
| 132 | template std::string* MakeCheckOpString<std::string, std::string>( |
| 133 | const std::string&, const std::string&, const char* name); |
| 134 | #endif |
| 135 | |
henrike@webrtc.org | c50bf7c | 2014-05-14 18:24:13 +0000 | [diff] [blame] | 136 | } // namespace rtc |
kwiberg | 2e48646 | 2016-08-23 05:54:25 -0700 | [diff] [blame] | 137 | |
| 138 | // Function to call from the C version of the RTC_CHECK and RTC_DCHECK macros. |
kjellander | bdf3072 | 2017-09-08 11:00:21 -0700 | [diff] [blame] | 139 | NO_RETURN void rtc_FatalMessage(const char* file, int line, const char* msg) { |
kwiberg | 2e48646 | 2016-08-23 05:54:25 -0700 | [diff] [blame] | 140 | rtc::FatalMessage(file, line).stream() << msg; |
| 141 | } |