Home | History | Annotate | Download | only in base
      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