Line data Source code
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(__GLIBC__) && !defined(__UCLIBC__)
20 : #include <cxxabi.h>
21 : #include <execinfo.h>
22 : #endif
23 :
24 : #if defined(WEBRTC_ANDROID)
25 : #define RTC_LOG_TAG "rtc"
26 : #include <android/log.h> // NOLINT
27 : #endif
28 :
29 : #if defined(WEBRTC_WIN)
30 : #include <windows.h>
31 : #endif
32 :
33 : #include "webrtc/base/checks.h"
34 : #include "webrtc/base/logging.h"
35 :
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 :
42 : namespace rtc {
43 :
44 0 : void VPrintError(const char* format, va_list args) {
45 : #if defined(WEBRTC_ANDROID)
46 : __android_log_vprint(ANDROID_LOG_ERROR, RTC_LOG_TAG, format, args);
47 : #else
48 0 : vfprintf(stderr, format, args);
49 : #endif
50 0 : }
51 :
52 0 : void PrintError(const char* format, ...) {
53 : va_list args;
54 0 : va_start(args, format);
55 0 : VPrintError(format, args);
56 0 : va_end(args);
57 0 : }
58 :
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 0 : void DumpBacktrace() {
63 : #if defined(__GLIBC__) && !defined(__UCLIBC__)
64 : void* trace[100];
65 0 : int size = backtrace(trace, sizeof(trace) / sizeof(*trace));
66 0 : char** symbols = backtrace_symbols(trace, size);
67 0 : PrintError("\n==== C stack trace ===============================\n\n");
68 0 : if (size == 0) {
69 0 : PrintError("(empty)\n");
70 0 : } else if (symbols == NULL) {
71 0 : PrintError("(no symbols)\n");
72 : } else {
73 0 : for (int i = 1; i < size; ++i) {
74 : char mangled[201];
75 0 : if (sscanf(symbols[i], "%*[^(]%*[(]%200[^)+]", mangled) == 1) { // NOLINT
76 0 : PrintError("%2d: ", i);
77 : int status;
78 : size_t length;
79 0 : char* demangled = abi::__cxa_demangle(mangled, NULL, &length, &status);
80 0 : PrintError("%s\n", demangled != NULL ? demangled : mangled);
81 0 : free(demangled);
82 : } else {
83 : // If parsing failed, at least print the unparsed symbol.
84 0 : PrintError("%s\n", symbols[i]);
85 : }
86 : }
87 : }
88 0 : free(symbols);
89 : #endif
90 0 : }
91 :
92 0 : FatalMessage::FatalMessage(const char* file, int line) {
93 0 : Init(file, line);
94 0 : }
95 :
96 0 : FatalMessage::FatalMessage(const char* file, int line, std::string* result) {
97 0 : Init(file, line);
98 0 : stream_ << "Check failed: " << *result << std::endl << "# ";
99 0 : delete result;
100 0 : }
101 :
102 0 : NO_RETURN FatalMessage::~FatalMessage() {
103 0 : fflush(stdout);
104 0 : fflush(stderr);
105 0 : stream_ << std::endl << "#" << std::endl;
106 0 : PrintError(stream_.str().c_str());
107 0 : DumpBacktrace();
108 0 : fflush(stderr);
109 0 : abort();
110 : }
111 :
112 0 : void FatalMessage::Init(const char* file, int line) {
113 0 : stream_ << std::endl << std::endl
114 0 : << "#" << std::endl
115 0 : << "# Fatal error in " << file << ", line " << line << std::endl
116 0 : << "# last system error: " << LAST_SYSTEM_ERROR << std::endl
117 0 : << "# ";
118 0 : }
119 :
120 : // MSVC doesn't like complex extern templates and DLLs.
121 : #if !defined(COMPILER_MSVC)
122 : // Explicit instantiations for commonly used comparisons.
123 : template std::string* MakeCheckOpString<int, int>(
124 : const int&, const int&, const char* names);
125 : template std::string* MakeCheckOpString<unsigned long, unsigned long>(
126 : const unsigned long&, const unsigned long&, const char* names);
127 : template std::string* MakeCheckOpString<unsigned long, unsigned int>(
128 : const unsigned long&, const unsigned int&, const char* names);
129 : template std::string* MakeCheckOpString<unsigned int, unsigned long>(
130 : const unsigned int&, const unsigned long&, const char* names);
131 : template std::string* MakeCheckOpString<std::string, std::string>(
132 : const std::string&, const std::string&, const char* name);
133 : #endif
134 :
135 : } // namespace rtc
136 :
137 : // Function to call from the C version of the RTC_CHECK and RTC_DCHECK macros.
138 0 : NO_RETURN void rtc_FatalMessage(const char* file, int line, const char* msg) {
139 0 : rtc::FatalMessage(file, line).stream() << msg;
140 : }
|