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