1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker * Copyright 2006 The WebRTC Project Authors. All rights reserved.
3*d9f75844SAndroid Build Coastguard Worker *
4*d9f75844SAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker */
10*d9f75844SAndroid Build Coastguard Worker
11*d9f75844SAndroid Build Coastguard Worker // Most of this was borrowed (with minor modifications) from V8's and Chromium's
12*d9f75844SAndroid Build Coastguard Worker // src/base/logging.cc.
13*d9f75844SAndroid Build Coastguard Worker
14*d9f75844SAndroid Build Coastguard Worker #include <cstdarg>
15*d9f75844SAndroid Build Coastguard Worker #include <cstdio>
16*d9f75844SAndroid Build Coastguard Worker #include <cstdlib>
17*d9f75844SAndroid Build Coastguard Worker
18*d9f75844SAndroid Build Coastguard Worker #include "absl/strings/string_view.h"
19*d9f75844SAndroid Build Coastguard Worker
20*d9f75844SAndroid Build Coastguard Worker #if defined(WEBRTC_ANDROID)
21*d9f75844SAndroid Build Coastguard Worker #define RTC_LOG_TAG_ANDROID "rtc"
22*d9f75844SAndroid Build Coastguard Worker #include <android/log.h> // NOLINT
23*d9f75844SAndroid Build Coastguard Worker #endif
24*d9f75844SAndroid Build Coastguard Worker
25*d9f75844SAndroid Build Coastguard Worker #if defined(WEBRTC_WIN)
26*d9f75844SAndroid Build Coastguard Worker #include <windows.h>
27*d9f75844SAndroid Build Coastguard Worker #endif
28*d9f75844SAndroid Build Coastguard Worker
29*d9f75844SAndroid Build Coastguard Worker #if defined(WEBRTC_WIN)
30*d9f75844SAndroid Build Coastguard Worker #define LAST_SYSTEM_ERROR (::GetLastError())
31*d9f75844SAndroid Build Coastguard Worker #elif defined(__native_client__) && __native_client__
32*d9f75844SAndroid Build Coastguard Worker #define LAST_SYSTEM_ERROR (0)
33*d9f75844SAndroid Build Coastguard Worker #elif defined(WEBRTC_POSIX)
34*d9f75844SAndroid Build Coastguard Worker #include <errno.h>
35*d9f75844SAndroid Build Coastguard Worker #define LAST_SYSTEM_ERROR (errno)
36*d9f75844SAndroid Build Coastguard Worker #endif // WEBRTC_WIN
37*d9f75844SAndroid Build Coastguard Worker
38*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h"
39*d9f75844SAndroid Build Coastguard Worker
40*d9f75844SAndroid Build Coastguard Worker namespace {
41*d9f75844SAndroid Build Coastguard Worker
42*d9f75844SAndroid Build Coastguard Worker #if defined(__GNUC__)
43*d9f75844SAndroid Build Coastguard Worker __attribute__((__format__(__printf__, 2, 3)))
44*d9f75844SAndroid Build Coastguard Worker #endif
AppendFormat(std::string * s,const char * fmt,...)45*d9f75844SAndroid Build Coastguard Worker void AppendFormat(std::string* s, const char* fmt, ...) {
46*d9f75844SAndroid Build Coastguard Worker va_list args, copy;
47*d9f75844SAndroid Build Coastguard Worker va_start(args, fmt);
48*d9f75844SAndroid Build Coastguard Worker va_copy(copy, args);
49*d9f75844SAndroid Build Coastguard Worker const int predicted_length = std::vsnprintf(nullptr, 0, fmt, copy);
50*d9f75844SAndroid Build Coastguard Worker va_end(copy);
51*d9f75844SAndroid Build Coastguard Worker
52*d9f75844SAndroid Build Coastguard Worker if (predicted_length > 0) {
53*d9f75844SAndroid Build Coastguard Worker const size_t size = s->size();
54*d9f75844SAndroid Build Coastguard Worker s->resize(size + predicted_length);
55*d9f75844SAndroid Build Coastguard Worker // Pass "+ 1" to vsnprintf to include space for the '\0'.
56*d9f75844SAndroid Build Coastguard Worker std::vsnprintf(&((*s)[size]), predicted_length + 1, fmt, args);
57*d9f75844SAndroid Build Coastguard Worker }
58*d9f75844SAndroid Build Coastguard Worker va_end(args);
59*d9f75844SAndroid Build Coastguard Worker }
60*d9f75844SAndroid Build Coastguard Worker } // namespace
61*d9f75844SAndroid Build Coastguard Worker
62*d9f75844SAndroid Build Coastguard Worker namespace rtc {
63*d9f75844SAndroid Build Coastguard Worker namespace webrtc_checks_impl {
64*d9f75844SAndroid Build Coastguard Worker
65*d9f75844SAndroid Build Coastguard Worker #if !defined(WEBRTC_CHROMIUM_BUILD)
WriteFatalLog(absl::string_view output)66*d9f75844SAndroid Build Coastguard Worker RTC_NORETURN void WriteFatalLog(absl::string_view output) {
67*d9f75844SAndroid Build Coastguard Worker #if defined(WEBRTC_ANDROID)
68*d9f75844SAndroid Build Coastguard Worker std::string output_str(output);
69*d9f75844SAndroid Build Coastguard Worker __android_log_print(ANDROID_LOG_ERROR, RTC_LOG_TAG_ANDROID, "%s\n",
70*d9f75844SAndroid Build Coastguard Worker output_str.c_str());
71*d9f75844SAndroid Build Coastguard Worker #endif
72*d9f75844SAndroid Build Coastguard Worker fflush(stdout);
73*d9f75844SAndroid Build Coastguard Worker fwrite(output.data(), output.size(), 1, stderr);
74*d9f75844SAndroid Build Coastguard Worker fflush(stderr);
75*d9f75844SAndroid Build Coastguard Worker #if defined(WEBRTC_WIN)
76*d9f75844SAndroid Build Coastguard Worker DebugBreak();
77*d9f75844SAndroid Build Coastguard Worker #endif
78*d9f75844SAndroid Build Coastguard Worker abort();
79*d9f75844SAndroid Build Coastguard Worker }
80*d9f75844SAndroid Build Coastguard Worker
WriteFatalLog(const char * file,int line,absl::string_view output)81*d9f75844SAndroid Build Coastguard Worker RTC_NORETURN void WriteFatalLog(const char* file,
82*d9f75844SAndroid Build Coastguard Worker int line,
83*d9f75844SAndroid Build Coastguard Worker absl::string_view output) {
84*d9f75844SAndroid Build Coastguard Worker WriteFatalLog(output);
85*d9f75844SAndroid Build Coastguard Worker }
86*d9f75844SAndroid Build Coastguard Worker
87*d9f75844SAndroid Build Coastguard Worker #endif // !defined(WEBRTC_CHROMIUM_BUILD)
88*d9f75844SAndroid Build Coastguard Worker
89*d9f75844SAndroid Build Coastguard Worker #if RTC_CHECK_MSG_ENABLED
90*d9f75844SAndroid Build Coastguard Worker // Reads one argument from args, appends it to s and advances fmt.
91*d9f75844SAndroid Build Coastguard Worker // Returns true iff an argument was sucessfully parsed.
ParseArg(va_list * args,const CheckArgType ** fmt,std::string * s)92*d9f75844SAndroid Build Coastguard Worker bool ParseArg(va_list* args, const CheckArgType** fmt, std::string* s) {
93*d9f75844SAndroid Build Coastguard Worker if (**fmt == CheckArgType::kEnd)
94*d9f75844SAndroid Build Coastguard Worker return false;
95*d9f75844SAndroid Build Coastguard Worker
96*d9f75844SAndroid Build Coastguard Worker switch (**fmt) {
97*d9f75844SAndroid Build Coastguard Worker case CheckArgType::kInt:
98*d9f75844SAndroid Build Coastguard Worker AppendFormat(s, "%d", va_arg(*args, int));
99*d9f75844SAndroid Build Coastguard Worker break;
100*d9f75844SAndroid Build Coastguard Worker case CheckArgType::kLong:
101*d9f75844SAndroid Build Coastguard Worker AppendFormat(s, "%ld", va_arg(*args, long));
102*d9f75844SAndroid Build Coastguard Worker break;
103*d9f75844SAndroid Build Coastguard Worker case CheckArgType::kLongLong:
104*d9f75844SAndroid Build Coastguard Worker AppendFormat(s, "%lld", va_arg(*args, long long));
105*d9f75844SAndroid Build Coastguard Worker break;
106*d9f75844SAndroid Build Coastguard Worker case CheckArgType::kUInt:
107*d9f75844SAndroid Build Coastguard Worker AppendFormat(s, "%u", va_arg(*args, unsigned));
108*d9f75844SAndroid Build Coastguard Worker break;
109*d9f75844SAndroid Build Coastguard Worker case CheckArgType::kULong:
110*d9f75844SAndroid Build Coastguard Worker AppendFormat(s, "%lu", va_arg(*args, unsigned long));
111*d9f75844SAndroid Build Coastguard Worker break;
112*d9f75844SAndroid Build Coastguard Worker case CheckArgType::kULongLong:
113*d9f75844SAndroid Build Coastguard Worker AppendFormat(s, "%llu", va_arg(*args, unsigned long long));
114*d9f75844SAndroid Build Coastguard Worker break;
115*d9f75844SAndroid Build Coastguard Worker case CheckArgType::kDouble:
116*d9f75844SAndroid Build Coastguard Worker AppendFormat(s, "%g", va_arg(*args, double));
117*d9f75844SAndroid Build Coastguard Worker break;
118*d9f75844SAndroid Build Coastguard Worker case CheckArgType::kLongDouble:
119*d9f75844SAndroid Build Coastguard Worker AppendFormat(s, "%Lg", va_arg(*args, long double));
120*d9f75844SAndroid Build Coastguard Worker break;
121*d9f75844SAndroid Build Coastguard Worker case CheckArgType::kCharP:
122*d9f75844SAndroid Build Coastguard Worker s->append(va_arg(*args, const char*));
123*d9f75844SAndroid Build Coastguard Worker break;
124*d9f75844SAndroid Build Coastguard Worker case CheckArgType::kStdString:
125*d9f75844SAndroid Build Coastguard Worker s->append(*va_arg(*args, const std::string*));
126*d9f75844SAndroid Build Coastguard Worker break;
127*d9f75844SAndroid Build Coastguard Worker case CheckArgType::kStringView: {
128*d9f75844SAndroid Build Coastguard Worker const absl::string_view sv = *va_arg(*args, const absl::string_view*);
129*d9f75844SAndroid Build Coastguard Worker s->append(sv.data(), sv.size());
130*d9f75844SAndroid Build Coastguard Worker break;
131*d9f75844SAndroid Build Coastguard Worker }
132*d9f75844SAndroid Build Coastguard Worker case CheckArgType::kVoidP:
133*d9f75844SAndroid Build Coastguard Worker AppendFormat(s, "%p", va_arg(*args, const void*));
134*d9f75844SAndroid Build Coastguard Worker break;
135*d9f75844SAndroid Build Coastguard Worker default:
136*d9f75844SAndroid Build Coastguard Worker s->append("[Invalid CheckArgType]");
137*d9f75844SAndroid Build Coastguard Worker return false;
138*d9f75844SAndroid Build Coastguard Worker }
139*d9f75844SAndroid Build Coastguard Worker (*fmt)++;
140*d9f75844SAndroid Build Coastguard Worker return true;
141*d9f75844SAndroid Build Coastguard Worker }
142*d9f75844SAndroid Build Coastguard Worker
FatalLog(const char * file,int line,const char * message,const CheckArgType * fmt,...)143*d9f75844SAndroid Build Coastguard Worker RTC_NORETURN void FatalLog(const char* file,
144*d9f75844SAndroid Build Coastguard Worker int line,
145*d9f75844SAndroid Build Coastguard Worker const char* message,
146*d9f75844SAndroid Build Coastguard Worker const CheckArgType* fmt,
147*d9f75844SAndroid Build Coastguard Worker ...) {
148*d9f75844SAndroid Build Coastguard Worker va_list args;
149*d9f75844SAndroid Build Coastguard Worker va_start(args, fmt);
150*d9f75844SAndroid Build Coastguard Worker
151*d9f75844SAndroid Build Coastguard Worker std::string s;
152*d9f75844SAndroid Build Coastguard Worker AppendFormat(&s,
153*d9f75844SAndroid Build Coastguard Worker "\n\n"
154*d9f75844SAndroid Build Coastguard Worker "#\n"
155*d9f75844SAndroid Build Coastguard Worker "# Fatal error in: %s, line %d\n"
156*d9f75844SAndroid Build Coastguard Worker "# last system error: %u\n"
157*d9f75844SAndroid Build Coastguard Worker "# Check failed: %s",
158*d9f75844SAndroid Build Coastguard Worker file, line, LAST_SYSTEM_ERROR, message);
159*d9f75844SAndroid Build Coastguard Worker
160*d9f75844SAndroid Build Coastguard Worker if (*fmt == CheckArgType::kCheckOp) {
161*d9f75844SAndroid Build Coastguard Worker // This log message was generated by RTC_CHECK_OP, so we have to complete
162*d9f75844SAndroid Build Coastguard Worker // the error message using the operands that have been passed as the first
163*d9f75844SAndroid Build Coastguard Worker // two arguments.
164*d9f75844SAndroid Build Coastguard Worker fmt++;
165*d9f75844SAndroid Build Coastguard Worker
166*d9f75844SAndroid Build Coastguard Worker std::string s1, s2;
167*d9f75844SAndroid Build Coastguard Worker if (ParseArg(&args, &fmt, &s1) && ParseArg(&args, &fmt, &s2))
168*d9f75844SAndroid Build Coastguard Worker AppendFormat(&s, " (%s vs. %s)\n# ", s1.c_str(), s2.c_str());
169*d9f75844SAndroid Build Coastguard Worker } else {
170*d9f75844SAndroid Build Coastguard Worker s.append("\n# ");
171*d9f75844SAndroid Build Coastguard Worker }
172*d9f75844SAndroid Build Coastguard Worker
173*d9f75844SAndroid Build Coastguard Worker // Append all the user-supplied arguments to the message.
174*d9f75844SAndroid Build Coastguard Worker while (ParseArg(&args, &fmt, &s))
175*d9f75844SAndroid Build Coastguard Worker ;
176*d9f75844SAndroid Build Coastguard Worker
177*d9f75844SAndroid Build Coastguard Worker va_end(args);
178*d9f75844SAndroid Build Coastguard Worker
179*d9f75844SAndroid Build Coastguard Worker WriteFatalLog(file, line, s);
180*d9f75844SAndroid Build Coastguard Worker }
181*d9f75844SAndroid Build Coastguard Worker #else // RTC_CHECK_MSG_ENABLED
FatalLog(const char * file,int line)182*d9f75844SAndroid Build Coastguard Worker RTC_NORETURN void FatalLog(const char* file, int line) {
183*d9f75844SAndroid Build Coastguard Worker std::string s;
184*d9f75844SAndroid Build Coastguard Worker AppendFormat(&s,
185*d9f75844SAndroid Build Coastguard Worker "\n\n"
186*d9f75844SAndroid Build Coastguard Worker "#\n"
187*d9f75844SAndroid Build Coastguard Worker "# Fatal error in: %s, line %d\n"
188*d9f75844SAndroid Build Coastguard Worker "# last system error: %u\n"
189*d9f75844SAndroid Build Coastguard Worker "# Check failed.\n"
190*d9f75844SAndroid Build Coastguard Worker "# ",
191*d9f75844SAndroid Build Coastguard Worker file, line, LAST_SYSTEM_ERROR);
192*d9f75844SAndroid Build Coastguard Worker WriteFatalLog(file, line, s);
193*d9f75844SAndroid Build Coastguard Worker }
194*d9f75844SAndroid Build Coastguard Worker #endif // RTC_CHECK_MSG_ENABLED
195*d9f75844SAndroid Build Coastguard Worker
196*d9f75844SAndroid Build Coastguard Worker #if RTC_DCHECK_IS_ON
197*d9f75844SAndroid Build Coastguard Worker
UnreachableCodeReached(const char * file,int line)198*d9f75844SAndroid Build Coastguard Worker RTC_NORETURN void UnreachableCodeReached(const char* file, int line) {
199*d9f75844SAndroid Build Coastguard Worker std::string s;
200*d9f75844SAndroid Build Coastguard Worker AppendFormat(&s,
201*d9f75844SAndroid Build Coastguard Worker "\n\n"
202*d9f75844SAndroid Build Coastguard Worker "#\n"
203*d9f75844SAndroid Build Coastguard Worker "# Unreachable code reached: %s, line %d\n"
204*d9f75844SAndroid Build Coastguard Worker "# last system error: %u\n"
205*d9f75844SAndroid Build Coastguard Worker "# ",
206*d9f75844SAndroid Build Coastguard Worker file, line, LAST_SYSTEM_ERROR);
207*d9f75844SAndroid Build Coastguard Worker WriteFatalLog(file, line, s);
208*d9f75844SAndroid Build Coastguard Worker }
209*d9f75844SAndroid Build Coastguard Worker
210*d9f75844SAndroid Build Coastguard Worker #else // !RTC_DCHECK_IS_ON
211*d9f75844SAndroid Build Coastguard Worker
UnreachableCodeReached()212*d9f75844SAndroid Build Coastguard Worker RTC_NORETURN void UnreachableCodeReached() {
213*d9f75844SAndroid Build Coastguard Worker std::string s;
214*d9f75844SAndroid Build Coastguard Worker AppendFormat(&s,
215*d9f75844SAndroid Build Coastguard Worker "\n\n"
216*d9f75844SAndroid Build Coastguard Worker "#\n"
217*d9f75844SAndroid Build Coastguard Worker "# Unreachable code reached (file and line unknown)\n"
218*d9f75844SAndroid Build Coastguard Worker "# last system error: %u\n"
219*d9f75844SAndroid Build Coastguard Worker "# ",
220*d9f75844SAndroid Build Coastguard Worker LAST_SYSTEM_ERROR);
221*d9f75844SAndroid Build Coastguard Worker WriteFatalLog(s);
222*d9f75844SAndroid Build Coastguard Worker }
223*d9f75844SAndroid Build Coastguard Worker
224*d9f75844SAndroid Build Coastguard Worker #endif // !RTC_DCHECK_IS_ON
225*d9f75844SAndroid Build Coastguard Worker
226*d9f75844SAndroid Build Coastguard Worker } // namespace webrtc_checks_impl
227*d9f75844SAndroid Build Coastguard Worker } // namespace rtc
228*d9f75844SAndroid Build Coastguard Worker
229*d9f75844SAndroid Build Coastguard Worker // Function to call from the C version of the RTC_CHECK and RTC_DCHECK macros.
rtc_FatalMessage(const char * file,int line,const char * msg)230*d9f75844SAndroid Build Coastguard Worker RTC_NORETURN void rtc_FatalMessage(const char* file,
231*d9f75844SAndroid Build Coastguard Worker int line,
232*d9f75844SAndroid Build Coastguard Worker const char* msg) {
233*d9f75844SAndroid Build Coastguard Worker #if RTC_CHECK_MSG_ENABLED
234*d9f75844SAndroid Build Coastguard Worker static constexpr rtc::webrtc_checks_impl::CheckArgType t[] = {
235*d9f75844SAndroid Build Coastguard Worker rtc::webrtc_checks_impl::CheckArgType::kEnd};
236*d9f75844SAndroid Build Coastguard Worker rtc::webrtc_checks_impl::FatalLog(file, line, msg, t);
237*d9f75844SAndroid Build Coastguard Worker #else
238*d9f75844SAndroid Build Coastguard Worker rtc::webrtc_checks_impl::FatalLog(file, line);
239*d9f75844SAndroid Build Coastguard Worker #endif
240*d9f75844SAndroid Build Coastguard Worker }
241