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 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__. 15 #include <cstdarg> 16 #include <cstdio> 17 #include <cstdlib> 18 19 #if defined(__GLIBCXX__) && !defined(__UCLIBC__) 20 #include <cxxabi.h> 21 #include <execinfo.h> 22 #endif 23 24 #if defined(WEBRTC_ANDROID) 25 #define LOG_TAG "rtc" 26 #include <android/log.h> // NOLINT 27 #endif 28 29 #include "webrtc/base/checks.h" 30 31 #if defined(_MSC_VER) 32 // Warning C4722: destructor never returns, potential memory leak. 33 // FatalMessage's dtor very intentionally aborts. 34 #pragma warning(disable:4722) 35 #endif 36 37 namespace rtc { 38 39 void VPrintError(const char* format, va_list args) { 40 #if defined(WEBRTC_ANDROID) 41 __android_log_vprint(ANDROID_LOG_ERROR, LOG_TAG, format, args); 42 #else 43 vfprintf(stderr, format, args); 44 #endif 45 } 46 47 void PrintError(const char* format, ...) { 48 va_list args; 49 va_start(args, format); 50 VPrintError(format, args); 51 va_end(args); 52 } 53 54 // TODO(ajm): This works on Mac (although the parsing fails) but I don't seem 55 // to get usable symbols on Linux. This is copied from V8. Chromium has a more 56 // advanced stace trace system; also more difficult to copy. 57 void DumpBacktrace() { 58 #if defined(__GLIBCXX__) && !defined(__UCLIBC__) 59 void* trace[100]; 60 int size = backtrace(trace, sizeof(trace) / sizeof(*trace)); 61 char** symbols = backtrace_symbols(trace, size); 62 PrintError("\n==== C stack trace ===============================\n\n"); 63 if (size == 0) { 64 PrintError("(empty)\n"); 65 } else if (symbols == NULL) { 66 PrintError("(no symbols)\n"); 67 } else { 68 for (int i = 1; i < size; ++i) { 69 char mangled[201]; 70 if (sscanf(symbols[i], "%*[^(]%*[(]%200[^)+]", mangled) == 1) { // NOLINT 71 PrintError("%2d: ", i); 72 int status; 73 size_t length; 74 char* demangled = abi::__cxa_demangle(mangled, NULL, &length, &status); 75 PrintError("%s\n", demangled != NULL ? demangled : mangled); 76 free(demangled); 77 } else { 78 // If parsing failed, at least print the unparsed symbol. 79 PrintError("%s\n", symbols[i]); 80 } 81 } 82 } 83 free(symbols); 84 #endif 85 } 86 87 FatalMessage::FatalMessage(const char* file, int line) { 88 Init(file, line); 89 } 90 91 FatalMessage::FatalMessage(const char* file, int line, std::string* result) { 92 Init(file, line); 93 stream_ << "Check failed: " << *result << std::endl << "# "; 94 delete result; 95 } 96 97 NO_RETURN FatalMessage::~FatalMessage() { 98 fflush(stdout); 99 fflush(stderr); 100 stream_ << std::endl << "#" << std::endl; 101 PrintError(stream_.str().c_str()); 102 DumpBacktrace(); 103 fflush(stderr); 104 abort(); 105 } 106 107 void FatalMessage::Init(const char* file, int line) { 108 stream_ << std::endl << std::endl << "#" << std::endl << "# Fatal error in " 109 << file << ", line " << line << std::endl << "# "; 110 } 111 112 // MSVC doesn't like complex extern templates and DLLs. 113 #if !defined(COMPILER_MSVC) 114 // Explicit instantiations for commonly used comparisons. 115 template std::string* MakeCheckOpString<int, int>( 116 const int&, const int&, const char* names); 117 template std::string* MakeCheckOpString<unsigned long, unsigned long>( 118 const unsigned long&, const unsigned long&, const char* names); 119 template std::string* MakeCheckOpString<unsigned long, unsigned int>( 120 const unsigned long&, const unsigned int&, const char* names); 121 template std::string* MakeCheckOpString<unsigned int, unsigned long>( 122 const unsigned int&, const unsigned long&, const char* names); 123 template std::string* MakeCheckOpString<std::string, std::string>( 124 const std::string&, const std::string&, const char* name); 125 #endif 126 127 } // namespace rtc 128