Commit 38e28257 by James Darpinian Committed by Commit Bot

Fix ASSERT macro not printing message

ANGLE's ASSERT macro was often not printing the error message before crashing. The printing happens in the destructor of a temporary object, but the temporary object is not guaranteed to be destroyed before ASSERT calls __builtin_trap(). This change fixes it by introducing a new FATAL log severity that moves the __builtin_trap() call into the destructor after the message is printed. Bug: 780507, angleproject:2215 Change-Id: Ica91e00d67cc95d7b59c3d59e6925ac3a93c19c5 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1521839 Commit-Queue: James Darpinian <jdarpinian@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent d25be8a1
...@@ -35,7 +35,7 @@ DebugAnnotator *g_debugAnnotator = nullptr; ...@@ -35,7 +35,7 @@ DebugAnnotator *g_debugAnnotator = nullptr;
std::mutex *g_debugMutex = nullptr; std::mutex *g_debugMutex = nullptr;
constexpr std::array<const char *, LOG_NUM_SEVERITIES> g_logSeverityNames = { constexpr std::array<const char *, LOG_NUM_SEVERITIES> g_logSeverityNames = {
{"EVENT", "WARN", "ERR"}}; {"EVENT", "WARN", "ERR", "FATAL"}};
constexpr const char *LogSeverityName(int severity) constexpr const char *LogSeverityName(int severity)
{ {
...@@ -157,7 +157,7 @@ LogMessage::~LogMessage() ...@@ -157,7 +157,7 @@ LogMessage::~LogMessage()
lock = std::unique_lock<std::mutex>(*g_debugMutex); lock = std::unique_lock<std::mutex>(*g_debugMutex);
} }
if (DebugAnnotationsInitialized() && (mSeverity == LOG_ERR || mSeverity == LOG_WARN)) if (DebugAnnotationsInitialized() && (mSeverity >= LOG_WARN))
{ {
g_debugAnnotator->logMessage(*this); g_debugAnnotator->logMessage(*this);
} }
...@@ -165,6 +165,11 @@ LogMessage::~LogMessage() ...@@ -165,6 +165,11 @@ LogMessage::~LogMessage()
{ {
Trace(getSeverity(), getMessage().c_str()); Trace(getSeverity(), getMessage().c_str());
} }
if (mSeverity == LOG_FATAL)
{
ANGLE_CRASH();
}
} }
void Trace(LogSeverity severity, const char *message) void Trace(LogSeverity severity, const char *message)
...@@ -190,14 +195,29 @@ void Trace(LogSeverity severity, const char *message) ...@@ -190,14 +195,29 @@ void Trace(LogSeverity severity, const char *message)
} }
} }
if (severity == LOG_ERR || severity == LOG_WARN) if (severity == LOG_FATAL || severity == LOG_ERR || severity == LOG_WARN)
{ {
#if defined(ANGLE_PLATFORM_ANDROID) #if defined(ANGLE_PLATFORM_ANDROID)
__android_log_print((severity == LOG_ERR) ? ANDROID_LOG_ERROR : ANDROID_LOG_WARN, "ANGLE", android_LogPriority android_priority = ANDROID_LOG_ERROR;
"%s: %s\n", LogSeverityName(severity), str.c_str()); switch (severity)
{
case LOG_WARN:
android_priority = ANDROID_LOG_WARN;
break;
case LOG_ERR:
android_priority = ANDROID_LOG_ERROR;
break;
case LOG_FATAL:
android_priority = ANDROID_LOG_FATAL;
break;
default:
UNREACHABLE();
}
__android_log_print(android_priority, "ANGLE", "%s: %s\n", LogSeverityName(severity),
str.c_str());
#else #else
// Note: we use fprintf because <iostream> includes static initializers. // Note: we use fprintf because <iostream> includes static initializers.
fprintf((severity == LOG_ERR) ? stderr : stdout, "%s: %s\n", LogSeverityName(severity), fprintf((severity >= LOG_ERR) ? stderr : stdout, "%s: %s\n", LogSeverityName(severity),
str.c_str()); str.c_str());
#endif #endif
} }
...@@ -205,7 +225,7 @@ void Trace(LogSeverity severity, const char *message) ...@@ -205,7 +225,7 @@ void Trace(LogSeverity severity, const char *message)
#if defined(ANGLE_PLATFORM_WINDOWS) && \ #if defined(ANGLE_PLATFORM_WINDOWS) && \
(defined(ANGLE_ENABLE_DEBUG_TRACE_TO_DEBUGGER) || !defined(NDEBUG)) (defined(ANGLE_ENABLE_DEBUG_TRACE_TO_DEBUGGER) || !defined(NDEBUG))
# if !defined(ANGLE_ENABLE_DEBUG_TRACE_TO_DEBUGGER) # if !defined(ANGLE_ENABLE_DEBUG_TRACE_TO_DEBUGGER)
if (severity == LOG_ERR) if (severity >= LOG_ERR)
# endif // !defined(ANGLE_ENABLE_DEBUG_TRACE_TO_DEBUGGER) # endif // !defined(ANGLE_ENABLE_DEBUG_TRACE_TO_DEBUGGER)
{ {
OutputDebugStringA(str.c_str()); OutputDebugStringA(str.c_str());
......
...@@ -46,7 +46,8 @@ using LogSeverity = int; ...@@ -46,7 +46,8 @@ using LogSeverity = int;
constexpr LogSeverity LOG_EVENT = 0; constexpr LogSeverity LOG_EVENT = 0;
constexpr LogSeverity LOG_WARN = 1; constexpr LogSeverity LOG_WARN = 1;
constexpr LogSeverity LOG_ERR = 2; constexpr LogSeverity LOG_ERR = 2;
constexpr LogSeverity LOG_NUM_SEVERITIES = 3; constexpr LogSeverity LOG_FATAL = 3;
constexpr LogSeverity LOG_NUM_SEVERITIES = 4;
void Trace(LogSeverity severity, const char *message); void Trace(LogSeverity severity, const char *message);
...@@ -191,10 +192,13 @@ std::ostream &FmtHex(std::ostream &os, T value) ...@@ -191,10 +192,13 @@ std::ostream &FmtHex(std::ostream &os, T value)
::gl::ClassName(__FUNCTION__, __LINE__, ::gl::LOG_WARN, ##__VA_ARGS__) ::gl::ClassName(__FUNCTION__, __LINE__, ::gl::LOG_WARN, ##__VA_ARGS__)
#define COMPACT_ANGLE_LOG_EX_ERR(ClassName, ...) \ #define COMPACT_ANGLE_LOG_EX_ERR(ClassName, ...) \
::gl::ClassName(__FUNCTION__, __LINE__, ::gl::LOG_ERR, ##__VA_ARGS__) ::gl::ClassName(__FUNCTION__, __LINE__, ::gl::LOG_ERR, ##__VA_ARGS__)
#define COMPACT_ANGLE_LOG_EX_FATAL(ClassName, ...) \
::gl::ClassName(__FUNCTION__, __LINE__, ::gl::LOG_FATAL, ##__VA_ARGS__)
#define COMPACT_ANGLE_LOG_EVENT COMPACT_ANGLE_LOG_EX_EVENT(LogMessage) #define COMPACT_ANGLE_LOG_EVENT COMPACT_ANGLE_LOG_EX_EVENT(LogMessage)
#define COMPACT_ANGLE_LOG_WARN COMPACT_ANGLE_LOG_EX_WARN(LogMessage) #define COMPACT_ANGLE_LOG_WARN COMPACT_ANGLE_LOG_EX_WARN(LogMessage)
#define COMPACT_ANGLE_LOG_ERR COMPACT_ANGLE_LOG_EX_ERR(LogMessage) #define COMPACT_ANGLE_LOG_ERR COMPACT_ANGLE_LOG_EX_ERR(LogMessage)
#define COMPACT_ANGLE_LOG_FATAL COMPACT_ANGLE_LOG_EX_FATAL(LogMessage)
#define ANGLE_LOG_IS_ON(severity) (::gl::priv::ShouldCreatePlatformLogMessage(::gl::LOG_##severity)) #define ANGLE_LOG_IS_ON(severity) (::gl::priv::ShouldCreatePlatformLogMessage(::gl::LOG_##severity))
...@@ -227,6 +231,7 @@ std::ostream &FmtHex(std::ostream &os, T value) ...@@ -227,6 +231,7 @@ std::ostream &FmtHex(std::ostream &os, T value)
#define WARN() ANGLE_LOG(WARN) #define WARN() ANGLE_LOG(WARN)
#define ERR() ANGLE_LOG(ERR) #define ERR() ANGLE_LOG(ERR)
#define FATAL() ANGLE_LOG(FATAL)
// A macro to log a performance event around a scope. // A macro to log a performance event around a scope.
#if defined(ANGLE_TRACE_ENABLED) #if defined(ANGLE_TRACE_ENABLED)
...@@ -251,11 +256,9 @@ std::ostream &FmtHex(std::ostream &os, T value) ...@@ -251,11 +256,9 @@ std::ostream &FmtHex(std::ostream &os, T value)
#if !defined(NDEBUG) #if !defined(NDEBUG)
# define ANGLE_ASSERT_IMPL(expression) assert(expression) # define ANGLE_ASSERT_IMPL(expression) assert(expression)
# define ANGLE_ASSERT_IMPL_IS_NORETURN 0
#else #else
// TODO(jmadill): Detect if debugger is attached and break. // TODO(jmadill): Detect if debugger is attached and break.
# define ANGLE_ASSERT_IMPL(expression) ANGLE_CRASH() # define ANGLE_ASSERT_IMPL(expression) ANGLE_CRASH()
# define ANGLE_ASSERT_IMPL_IS_NORETURN 1
#endif // !defined(NDEBUG) #endif // !defined(NDEBUG)
// Note that gSwallowStream is used instead of an arbitrary LOG() stream to avoid the creation of an // Note that gSwallowStream is used instead of an arbitrary LOG() stream to avoid the creation of an
...@@ -272,17 +275,16 @@ std::ostream &FmtHex(std::ostream &os, T value) ...@@ -272,17 +275,16 @@ std::ostream &FmtHex(std::ostream &os, T value)
// A macro asserting a condition and outputting failures to the debug log // A macro asserting a condition and outputting failures to the debug log
#if defined(ANGLE_ENABLE_ASSERTS) #if defined(ANGLE_ENABLE_ASSERTS)
# define ASSERT(expression) \ # define ASSERT(expression) \
(expression ? static_cast<void>(0) \ (expression ? static_cast<void>(0) \
: ((ERR() << "\t! Assert failed in " << __FUNCTION__ << "(" << __LINE__ \ : (FATAL() << "\t! Assert failed in " << __FUNCTION__ << "(" << __LINE__ \
<< "): " << #expression), \ << "): " << #expression))
ANGLE_ASSERT_IMPL(expression)))
# define UNREACHABLE_IS_NORETURN ANGLE_ASSERT_IMPL_IS_NORETURN
#else #else
# define ASSERT(condition) ANGLE_EAT_STREAM_PARAMETERS << !(condition) # define ASSERT(condition) ANGLE_EAT_STREAM_PARAMETERS << !(condition)
# define UNREACHABLE_IS_NORETURN 0
#endif // defined(ANGLE_ENABLE_ASSERTS) #endif // defined(ANGLE_ENABLE_ASSERTS)
#define UNREACHABLE_IS_NORETURN 0
#define ANGLE_UNUSED_VARIABLE(variable) (static_cast<void>(variable)) #define ANGLE_UNUSED_VARIABLE(variable) (static_cast<void>(variable))
// A macro to indicate unimplemented functionality // A macro to indicate unimplemented functionality
...@@ -300,12 +302,11 @@ std::ostream &FmtHex(std::ostream &os, T value) ...@@ -300,12 +302,11 @@ std::ostream &FmtHex(std::ostream &os, T value)
} while (0) } while (0)
// A macro for code which is not expected to be reached under valid assumptions // A macro for code which is not expected to be reached under valid assumptions
# define UNREACHABLE() \ # define UNREACHABLE() \
do \ do \
{ \ { \
ERR() << "\t! Unreachable reached: " << __FUNCTION__ << "(" << __FILE__ << ":" \ FATAL() << "\t! Unreachable reached: " << __FUNCTION__ << "(" << __FILE__ << ":" \
<< __LINE__ << ")"; \ << __LINE__ << ")"; \
ASSERT(false); \
} while (0) } while (0)
#else #else
# define UNIMPLEMENTED() \ # define UNIMPLEMENTED() \
......
...@@ -41,6 +41,7 @@ void LoggingAnnotator::logMessage(const gl::LogMessage &msg) const ...@@ -41,6 +41,7 @@ void LoggingAnnotator::logMessage(const gl::LogMessage &msg) const
{ {
switch (msg.getSeverity()) switch (msg.getSeverity())
{ {
case gl::LOG_FATAL:
case gl::LOG_ERR: case gl::LOG_ERR:
plat->logError(plat, msg.getMessage().c_str()); plat->logError(plat, msg.getMessage().c_str());
break; break;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment