blob: 1bddf228b66eec7f42571a43905fd422d7eb8ef2 [file] [log] [blame]
henrike@webrtc.orgf0488722014-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.orga5b78692014-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
andrew@webrtc.org34a67642014-09-02 19:00:4514#include <cstdarg>
andrew@webrtc.org4ca66d62014-09-10 03:24:3615#include <cstdio>
16#include <cstdlib>
andrew@webrtc.orga5b78692014-08-28 16:28:2617
andrew@webrtc.org34a67642014-09-02 19:00:4518#if defined(WEBRTC_ANDROID)
Mirko Bonadei8ed8e562017-10-27 07:43:5319#define RTC_LOG_TAG_ANDROID "rtc"
andrew@webrtc.orga5b78692014-08-28 16:28:2620#include <android/log.h> // NOLINT
21#endif
22
tommie8be6ff2016-04-22 08:22:2423#if defined(WEBRTC_WIN)
24#include <windows.h>
25#endif
26
Patrik Höglunda8005cf2017-12-13 15:05:4227#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 23:32:0332#include <errno.h>
Patrik Höglunda8005cf2017-12-13 15:05:4233#define LAST_SYSTEM_ERROR (errno)
34#endif // WEBRTC_WIN
35
Mirko Bonadei92ea95e2017-09-15 04:47:3136#include "rtc_base/checks.h"
henrike@webrtc.orgf0488722014-05-13 18:00:2637
Jonas Olsson5c3cf052018-09-06 08:47:4238namespace {
39#if defined(__GNUC__)
40__attribute__((__format__(__printf__, 2, 3)))
41#endif
Mirko Bonadeid4a37a62019-03-11 09:31:2242void AppendFormat(std::string* s, const char* fmt, ...) {
Jonas Olsson5c3cf052018-09-06 08:47:4243 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 09:31:2257} // namespace
Jonas Olsson5c3cf052018-09-06 08:47:4258
henrike@webrtc.orgc50bf7c2014-05-14 18:24:1359namespace rtc {
Jonas Olssonf8e5c112018-06-14 11:14:2260namespace webrtc_checks_impl {
Jonas Olssond000b0a2018-07-03 10:07:5361
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 08:47:4264bool ParseArg(va_list* args, const CheckArgType** fmt, std::string* s) {
Jonas Olssond000b0a2018-07-03 10:07:5365 if (**fmt == CheckArgType::kEnd)
66 return false;
67
68 switch (**fmt) {
69 case CheckArgType::kInt:
Jonas Olsson5c3cf052018-09-06 08:47:4270 AppendFormat(s, "%d", va_arg(*args, int));
Jonas Olssond000b0a2018-07-03 10:07:5371 break;
72 case CheckArgType::kLong:
Jonas Olsson5c3cf052018-09-06 08:47:4273 AppendFormat(s, "%ld", va_arg(*args, long));
Jonas Olssond000b0a2018-07-03 10:07:5374 break;
75 case CheckArgType::kLongLong:
Jonas Olsson5c3cf052018-09-06 08:47:4276 AppendFormat(s, "%lld", va_arg(*args, long long));
Jonas Olssond000b0a2018-07-03 10:07:5377 break;
78 case CheckArgType::kUInt:
Jonas Olsson5c3cf052018-09-06 08:47:4279 AppendFormat(s, "%u", va_arg(*args, unsigned));
Jonas Olssond000b0a2018-07-03 10:07:5380 break;
81 case CheckArgType::kULong:
Jonas Olsson5c3cf052018-09-06 08:47:4282 AppendFormat(s, "%lu", va_arg(*args, unsigned long));
Jonas Olssond000b0a2018-07-03 10:07:5383 break;
84 case CheckArgType::kULongLong:
Jonas Olsson5c3cf052018-09-06 08:47:4285 AppendFormat(s, "%llu", va_arg(*args, unsigned long long));
Jonas Olssond000b0a2018-07-03 10:07:5386 break;
87 case CheckArgType::kDouble:
Jonas Olsson5c3cf052018-09-06 08:47:4288 AppendFormat(s, "%g", va_arg(*args, double));
Jonas Olssond000b0a2018-07-03 10:07:5389 break;
90 case CheckArgType::kLongDouble:
Jonas Olsson5c3cf052018-09-06 08:47:4291 AppendFormat(s, "%Lg", va_arg(*args, long double));
Jonas Olssond000b0a2018-07-03 10:07:5392 break;
93 case CheckArgType::kCharP:
Jonas Olsson5c3cf052018-09-06 08:47:4294 s->append(va_arg(*args, const char*));
Jonas Olssond000b0a2018-07-03 10:07:5395 break;
96 case CheckArgType::kStdString:
Jonas Olsson5c3cf052018-09-06 08:47:4297 s->append(*va_arg(*args, const std::string*));
Jonas Olssond000b0a2018-07-03 10:07:5398 break;
Mirko Bonadeid4a37a62019-03-11 09:31:2299 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 10:07:53104 case CheckArgType::kVoidP:
Jonas Olsson5c3cf052018-09-06 08:47:42105 AppendFormat(s, "%p", va_arg(*args, const void*));
Jonas Olssond000b0a2018-07-03 10:07:53106 break;
107 default:
Jonas Olsson5c3cf052018-09-06 08:47:42108 s->append("[Invalid CheckArgType]");
Jonas Olssond000b0a2018-07-03 10:07:53109 return false;
110 }
111 (*fmt)++;
112 return true;
113}
114
Jonas Olssonf8e5c112018-06-14 11:14:22115RTC_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:26122
Jonas Olsson5c3cf052018-09-06 08:47:42123 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 11:14:22131
Jonas Olssond000b0a2018-07-03 10:07:53132 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 08:47:42138 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 10:07:53141 } else {
Jonas Olsson5c3cf052018-09-06 08:47:42142 s.append("\n# ");
Jonas Olssonf8e5c112018-06-14 11:14:22143 }
Jonas Olssond000b0a2018-07-03 10:07:53144
145 // Append all the user-supplied arguments to the message.
Jonas Olsson5c3cf052018-09-06 08:47:42146 while (ParseArg(&args, &fmt, &s))
Jonas Olssond000b0a2018-07-03 10:07:53147 ;
148
Jonas Olssonf8e5c112018-06-14 11:14:22149 va_end(args);
150
Jonas Olssonf8e5c112018-06-14 11:14:22151 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:13164} // namespace rtc
kwiberg2e486462016-08-23 12:54:25165
166// Function to call from the C version of the RTC_CHECK and RTC_DCHECK macros.
Jonas Olssona4d87372019-07-05 17:08:33167RTC_NORETURN void rtc_FatalMessage(const char* file,
168 int line,
Fredrik Solenberg500e75b2018-05-23 09:49:01169 const char* msg) {
Jonas Olssonf8e5c112018-06-14 11:14:22170 static constexpr rtc::webrtc_checks_impl::CheckArgType t[] = {
171 rtc::webrtc_checks_impl::CheckArgType::kEnd};
172 FatalLog(file, line, msg, t);
kwiberg2e486462016-08-23 12:54:25173}