/* * Copyright 2006 The WebRTC Project Authors. All rights reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ // Most of this was borrowed (with minor modifications) from V8's and Chromium's // src/base/logging.cc. #include #include #include #if defined(WEBRTC_ANDROID) #define RTC_LOG_TAG_ANDROID "rtc" #include // NOLINT #endif #if defined(WEBRTC_WIN) #include #endif #if defined(WEBRTC_WIN) #define LAST_SYSTEM_ERROR (::GetLastError()) #elif defined(__native_client__) && __native_client__ #define LAST_SYSTEM_ERROR (0) #elif defined(WEBRTC_POSIX) #include #define LAST_SYSTEM_ERROR (errno) #endif // WEBRTC_WIN #include "rtc_base/checks.h" namespace rtc { namespace webrtc_checks_impl { // Reads one argument from args, appends it to s and advances fmt. // Returns true iff an argument was sucessfully parsed. bool ParseArg(va_list* args, const CheckArgType** fmt, std::ostream& s) { // no-presubmit-check TODO(webrtc:8982) if (**fmt == CheckArgType::kEnd) return false; switch (**fmt) { case CheckArgType::kInt: s << va_arg(*args, int); break; case CheckArgType::kLong: s << va_arg(*args, long); break; case CheckArgType::kLongLong: s << va_arg(*args, long long); break; case CheckArgType::kUInt: s << va_arg(*args, unsigned); break; case CheckArgType::kULong: s << va_arg(*args, unsigned long); break; case CheckArgType::kULongLong: s << va_arg(*args, unsigned long long); break; case CheckArgType::kDouble: s << va_arg(*args, double); break; case CheckArgType::kLongDouble: s << va_arg(*args, long double); break; case CheckArgType::kCharP: s << va_arg(*args, const char*); break; case CheckArgType::kStdString: s << *va_arg(*args, const std::string*); break; case CheckArgType::kVoidP: s << reinterpret_cast(va_arg(*args, const void*)); break; default: s << "[Invalid CheckArgType:" << static_cast(**fmt) << "]"; return false; } (*fmt)++; return true; } RTC_NORETURN void FatalLog(const char* file, int line, const char* message, const CheckArgType* fmt, ...) { va_list args; va_start(args, fmt); std::ostringstream ss; // no-presubmit-check TODO(webrtc:8982) ss << "\n\n#\n# Fatal error in: " << file << ", line " << line << "\n# last system error: " << LAST_SYSTEM_ERROR << "\n# Check failed: "; if (*fmt == CheckArgType::kCheckOp) { // This log message was generated by RTC_CHECK_OP, so we have to complete // the error message using the operands that have been passed as the first // two arguments. fmt++; std::ostringstream s1, s2; // no-presubmit-check TODO(webrtc:8982) if (ParseArg(&args, &fmt, s1) && ParseArg(&args, &fmt, s2)) ss << message << " (" << s1.str() << " vs. " << s2.str() << ")\n# "; } else { ss << message << "\n# "; } // Append all the user-supplied arguments to the message. while (ParseArg(&args, &fmt, ss)) ; va_end(args); std::string s = ss.str(); const char* output = s.c_str(); #if defined(WEBRTC_ANDROID) __android_log_print(ANDROID_LOG_ERROR, RTC_LOG_TAG_ANDROID, "%s\n", output); #endif fflush(stdout); fprintf(stderr, "%s", output); fflush(stderr); abort(); } } // namespace webrtc_checks_impl } // namespace rtc // Function to call from the C version of the RTC_CHECK and RTC_DCHECK macros. RTC_NORETURN void rtc_FatalMessage(const char* file, int line, const char* msg) { static constexpr rtc::webrtc_checks_impl::CheckArgType t[] = { rtc::webrtc_checks_impl::CheckArgType::kEnd}; FatalLog(file, line, msg, t); }