blob: 6aaaf9ff83bee8cb70452c0be1b864c40f6eb0b5 [file] [log] [blame]
henrike@webrtc.org47be73b2014-05-13 18:00:261/*
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.org54ade8b2014-08-28 16:28:2611// 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.orga70332f2014-09-02 19:00:4515#include <cstdarg>
andrew@webrtc.org0d64dac2014-09-10 03:24:3616#include <cstdio>
17#include <cstdlib>
andrew@webrtc.org54ade8b2014-08-28 16:28:2618
19#if defined(__GLIBCXX__) && !defined(__UCLIBC__)
20#include <cxxabi.h>
21#include <execinfo.h>
22#endif
23
andrew@webrtc.orga70332f2014-09-02 19:00:4524#if defined(WEBRTC_ANDROID)
tommi46311242016-04-22 08:22:2425#define RTC_LOG_TAG "rtc"
andrew@webrtc.org54ade8b2014-08-28 16:28:2626#include <android/log.h> // NOLINT
27#endif
28
tommi46311242016-04-22 08:22:2429#if defined(WEBRTC_WIN)
30#include <windows.h>
31#endif
32
henrike@webrtc.org47be73b2014-05-13 18:00:2633#include "webrtc/base/checks.h"
tommi46311242016-04-22 08:22:2434#include "webrtc/base/logging.h"
henrike@webrtc.org47be73b2014-05-13 18:00:2635
andrew@webrtc.org54ade8b2014-08-28 16:28:2636#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.orgb2eea5c2014-05-14 18:24:1342namespace rtc {
43
andrew@webrtc.org54ade8b2014-08-28 16:28:2644void VPrintError(const char* format, va_list args) {
45#if defined(WEBRTC_ANDROID)
tommi46311242016-04-22 08:22:2446 __android_log_vprint(ANDROID_LOG_ERROR, RTC_LOG_TAG, format, args);
andrew@webrtc.org54ade8b2014-08-28 16:28:2647#else
48 vfprintf(stderr, format, args);
49#endif
50}
henrike@webrtc.org47be73b2014-05-13 18:00:2651
andrew@webrtc.org54ade8b2014-08-28 16:28:2652void PrintError(const char* format, ...) {
53 va_list args;
54 va_start(args, format);
55 VPrintError(format, args);
56 va_end(args);
57}
henrike@webrtc.org47be73b2014-05-13 18:00:2658
andrew@webrtc.org54ade8b2014-08-28 16:28:2659// 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.
62void DumpBacktrace() {
63#if defined(__GLIBCXX__) && !defined(__UCLIBC__)
64 void* trace[100];
andrew@webrtc.orga70332f2014-09-02 19:00:4565 int size = backtrace(trace, sizeof(trace) / sizeof(*trace));
andrew@webrtc.org54ade8b2014-08-28 16:28:2666 char** symbols = backtrace_symbols(trace, size);
67 PrintError("\n==== C stack trace ===============================\n\n");
68 if (size == 0) {
69 PrintError("(empty)\n");
70 } else if (symbols == NULL) {
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;
79 char* demangled = abi::__cxa_demangle(mangled, NULL, &length, &status);
80 PrintError("%s\n", demangled != NULL ? demangled : mangled);
81 free(demangled);
82 } else {
83 // If parsing failed, at least print the unparsed symbol.
84 PrintError("%s\n", symbols[i]);
85 }
86 }
87 }
88 free(symbols);
89#endif
90}
91
92FatalMessage::FatalMessage(const char* file, int line) {
93 Init(file, line);
94}
95
96FatalMessage::FatalMessage(const char* file, int line, std::string* result) {
97 Init(file, line);
98 stream_ << "Check failed: " << *result << std::endl << "# ";
99 delete result;
100}
101
102NO_RETURN FatalMessage::~FatalMessage() {
103 fflush(stdout);
104 fflush(stderr);
105 stream_ << std::endl << "#" << std::endl;
106 PrintError(stream_.str().c_str());
107 DumpBacktrace();
108 fflush(stderr);
henrike@webrtc.org47be73b2014-05-13 18:00:26109 abort();
110}
henrike@webrtc.orgb2eea5c2014-05-14 18:24:13111
andrew@webrtc.org54ade8b2014-08-28 16:28:26112void FatalMessage::Init(const char* file, int line) {
tommi46311242016-04-22 08:22:24113 stream_ << std::endl << std::endl
114 << "#" << std::endl
115 << "# Fatal error in " << file << ", line " << line << std::endl
116 << "# last system error: " << LAST_SYSTEM_ERROR << std::endl
117 << "# ";
andrew@webrtc.org54ade8b2014-08-28 16:28:26118}
119
120// MSVC doesn't like complex extern templates and DLLs.
121#if !defined(COMPILER_MSVC)
122// Explicit instantiations for commonly used comparisons.
123template std::string* MakeCheckOpString<int, int>(
124 const int&, const int&, const char* names);
125template std::string* MakeCheckOpString<unsigned long, unsigned long>(
126 const unsigned long&, const unsigned long&, const char* names);
127template std::string* MakeCheckOpString<unsigned long, unsigned int>(
128 const unsigned long&, const unsigned int&, const char* names);
129template std::string* MakeCheckOpString<unsigned int, unsigned long>(
130 const unsigned int&, const unsigned long&, const char* names);
131template std::string* MakeCheckOpString<std::string, std::string>(
132 const std::string&, const std::string&, const char* name);
133#endif
134
henrike@webrtc.orgb2eea5c2014-05-14 18:24:13135} // namespace rtc
kwiberg00701192016-08-23 12:54:25136
137// Function to call from the C version of the RTC_CHECK and RTC_DCHECK macros.
138NO_RETURN void rtc_FatalMessage(const char* file, int line, const char* msg) {
139 rtc::FatalMessage(file, line).stream() << msg;
140}