blob: 1bddf228b66eec7f42571a43905fd422d7eb8ef2 [file] [log] [blame]
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001/*
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.orga5b78692014-08-28 16:28:26 +000011// Most of this was borrowed (with minor modifications) from V8's and Chromium's
12// src/base/logging.cc.
13
andrew@webrtc.org34a67642014-09-02 19:00:45 +000014#include <cstdarg>
andrew@webrtc.org4ca66d62014-09-10 03:24:36 +000015#include <cstdio>
16#include <cstdlib>
andrew@webrtc.orga5b78692014-08-28 16:28:26 +000017
andrew@webrtc.org34a67642014-09-02 19:00:45 +000018#if defined(WEBRTC_ANDROID)
Mirko Bonadei8ed8e562017-10-27 09:43:53 +020019#define RTC_LOG_TAG_ANDROID "rtc"
andrew@webrtc.orga5b78692014-08-28 16:28:26 +000020#include <android/log.h> // NOLINT
21#endif
22
tommie8be6ff2016-04-22 01:22:24 -070023#if defined(WEBRTC_WIN)
24#include <windows.h>
25#endif
26
Patrik Höglunda8005cf2017-12-13 16:05:42 +010027#if defined(WEBRTC_WIN)
28#define LAST_SYSTEM_ERROR (::GetLastError())
29#elif defined(__native_client__) && __native_client__
30#define LAST_SYSTEM_ERROR (0)
31#elif defined(WEBRTC_POSIX)
Jiawei Ou3b1df672018-01-29 15:32:03 -080032#include <errno.h>
Patrik Höglunda8005cf2017-12-13 16:05:42 +010033#define LAST_SYSTEM_ERROR (errno)
34#endif // WEBRTC_WIN
35
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020036#include "rtc_base/checks.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000037
Jonas Olsson5c3cf052018-09-06 10:47:42 +020038namespace {
39#if defined(__GNUC__)
40__attribute__((__format__(__printf__, 2, 3)))
41#endif
Mirko Bonadeid4a37a62019-03-11 10:31:22 +010042void AppendFormat(std::string* s, const char* fmt, ...) {
Jonas Olsson5c3cf052018-09-06 10:47:42 +020043 va_list args, copy;
44 va_start(args, fmt);
45 va_copy(copy, args);
46 const int predicted_length = std::vsnprintf(nullptr, 0, fmt, copy);
47 va_end(copy);
48
49 if (predicted_length > 0) {
50 const size_t size = s->size();
51 s->resize(size + predicted_length);
52 // Pass "+ 1" to vsnprintf to include space for the '\0'.
53 std::vsnprintf(&((*s)[size]), predicted_length + 1, fmt, args);
54 }
55 va_end(args);
56}
Mirko Bonadeid4a37a62019-03-11 10:31:22 +010057} // namespace
Jonas Olsson5c3cf052018-09-06 10:47:42 +020058
henrike@webrtc.orgc50bf7c2014-05-14 18:24:13 +000059namespace rtc {
Jonas Olssonf8e5c112018-06-14 13:14:22 +020060namespace webrtc_checks_impl {
Jonas Olssond000b0a2018-07-03 12:07:53 +020061
62// Reads one argument from args, appends it to s and advances fmt.
63// Returns true iff an argument was sucessfully parsed.
Jonas Olsson5c3cf052018-09-06 10:47:42 +020064bool ParseArg(va_list* args, const CheckArgType** fmt, std::string* s) {
Jonas Olssond000b0a2018-07-03 12:07:53 +020065 if (**fmt == CheckArgType::kEnd)
66 return false;
67
68 switch (**fmt) {
69 case CheckArgType::kInt:
Jonas Olsson5c3cf052018-09-06 10:47:42 +020070 AppendFormat(s, "%d", va_arg(*args, int));
Jonas Olssond000b0a2018-07-03 12:07:53 +020071 break;
72 case CheckArgType::kLong:
Jonas Olsson5c3cf052018-09-06 10:47:42 +020073 AppendFormat(s, "%ld", va_arg(*args, long));
Jonas Olssond000b0a2018-07-03 12:07:53 +020074 break;
75 case CheckArgType::kLongLong:
Jonas Olsson5c3cf052018-09-06 10:47:42 +020076 AppendFormat(s, "%lld", va_arg(*args, long long));
Jonas Olssond000b0a2018-07-03 12:07:53 +020077 break;
78 case CheckArgType::kUInt:
Jonas Olsson5c3cf052018-09-06 10:47:42 +020079 AppendFormat(s, "%u", va_arg(*args, unsigned));
Jonas Olssond000b0a2018-07-03 12:07:53 +020080 break;
81 case CheckArgType::kULong:
Jonas Olsson5c3cf052018-09-06 10:47:42 +020082 AppendFormat(s, "%lu", va_arg(*args, unsigned long));
Jonas Olssond000b0a2018-07-03 12:07:53 +020083 break;
84 case CheckArgType::kULongLong:
Jonas Olsson5c3cf052018-09-06 10:47:42 +020085 AppendFormat(s, "%llu", va_arg(*args, unsigned long long));
Jonas Olssond000b0a2018-07-03 12:07:53 +020086 break;
87 case CheckArgType::kDouble:
Jonas Olsson5c3cf052018-09-06 10:47:42 +020088 AppendFormat(s, "%g", va_arg(*args, double));
Jonas Olssond000b0a2018-07-03 12:07:53 +020089 break;
90 case CheckArgType::kLongDouble:
Jonas Olsson5c3cf052018-09-06 10:47:42 +020091 AppendFormat(s, "%Lg", va_arg(*args, long double));
Jonas Olssond000b0a2018-07-03 12:07:53 +020092 break;
93 case CheckArgType::kCharP:
Jonas Olsson5c3cf052018-09-06 10:47:42 +020094 s->append(va_arg(*args, const char*));
Jonas Olssond000b0a2018-07-03 12:07:53 +020095 break;
96 case CheckArgType::kStdString:
Jonas Olsson5c3cf052018-09-06 10:47:42 +020097 s->append(*va_arg(*args, const std::string*));
Jonas Olssond000b0a2018-07-03 12:07:53 +020098 break;
Mirko Bonadeid4a37a62019-03-11 10:31:22 +010099 case CheckArgType::kStringView: {
100 const absl::string_view sv = *va_arg(*args, const absl::string_view*);
101 s->append(sv.data(), sv.size());
102 break;
103 }
Jonas Olssond000b0a2018-07-03 12:07:53 +0200104 case CheckArgType::kVoidP:
Jonas Olsson5c3cf052018-09-06 10:47:42 +0200105 AppendFormat(s, "%p", va_arg(*args, const void*));
Jonas Olssond000b0a2018-07-03 12:07:53 +0200106 break;
107 default:
Jonas Olsson5c3cf052018-09-06 10:47:42 +0200108 s->append("[Invalid CheckArgType]");
Jonas Olssond000b0a2018-07-03 12:07:53 +0200109 return false;
110 }
111 (*fmt)++;
112 return true;
113}
114
Jonas Olssonf8e5c112018-06-14 13:14:22 +0200115RTC_NORETURN void FatalLog(const char* file,
116 int line,
117 const char* message,
118 const CheckArgType* fmt,
119 ...) {
120 va_list args;
121 va_start(args, fmt);
andrew@webrtc.orga5b78692014-08-28 16:28:26 +0000122
Jonas Olsson5c3cf052018-09-06 10:47:42 +0200123 std::string s;
124 AppendFormat(&s,
125 "\n\n"
126 "#\n"
127 "# Fatal error in: %s, line %d\n"
128 "# last system error: %u\n"
129 "# Check failed: %s",
130 file, line, LAST_SYSTEM_ERROR, message);
Jonas Olssonf8e5c112018-06-14 13:14:22 +0200131
Jonas Olssond000b0a2018-07-03 12:07:53 +0200132 if (*fmt == CheckArgType::kCheckOp) {
133 // This log message was generated by RTC_CHECK_OP, so we have to complete
134 // the error message using the operands that have been passed as the first
135 // two arguments.
136 fmt++;
137
Jonas Olsson5c3cf052018-09-06 10:47:42 +0200138 std::string s1, s2;
139 if (ParseArg(&args, &fmt, &s1) && ParseArg(&args, &fmt, &s2))
140 AppendFormat(&s, " (%s vs. %s)\n# ", s1.c_str(), s2.c_str());
Jonas Olssond000b0a2018-07-03 12:07:53 +0200141 } else {
Jonas Olsson5c3cf052018-09-06 10:47:42 +0200142 s.append("\n# ");
Jonas Olssonf8e5c112018-06-14 13:14:22 +0200143 }
Jonas Olssond000b0a2018-07-03 12:07:53 +0200144
145 // Append all the user-supplied arguments to the message.
Jonas Olsson5c3cf052018-09-06 10:47:42 +0200146 while (ParseArg(&args, &fmt, &s))
Jonas Olssond000b0a2018-07-03 12:07:53 +0200147 ;
148
Jonas Olssonf8e5c112018-06-14 13:14:22 +0200149 va_end(args);
150
Jonas Olssonf8e5c112018-06-14 13:14:22 +0200151 const char* output = s.c_str();
152
153#if defined(WEBRTC_ANDROID)
154 __android_log_print(ANDROID_LOG_ERROR, RTC_LOG_TAG_ANDROID, "%s\n", output);
155#endif
156
157 fflush(stdout);
158 fprintf(stderr, "%s", output);
159 fflush(stderr);
160 abort();
161}
162
163} // namespace webrtc_checks_impl
henrike@webrtc.orgc50bf7c2014-05-14 18:24:13 +0000164} // namespace rtc
kwiberg2e486462016-08-23 05:54:25 -0700165
166// Function to call from the C version of the RTC_CHECK and RTC_DCHECK macros.
Jonas Olssona4d87372019-07-05 19:08:33 +0200167RTC_NORETURN void rtc_FatalMessage(const char* file,
168 int line,
Fredrik Solenberg500e75b2018-05-23 11:49:01 +0200169 const char* msg) {
Jonas Olssonf8e5c112018-06-14 13:14:22 +0200170 static constexpr rtc::webrtc_checks_impl::CheckArgType t[] = {
171 rtc::webrtc_checks_impl::CheckArgType::kEnd};
172 FatalLog(file, line, msg, t);
kwiberg2e486462016-08-23 05:54:25 -0700173}