xref: /aosp_15_r20/external/webrtc/rtc_base/checks.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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