summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Gampe <agampe@google.com>2016-09-08 11:03:58 -0700
committerAndreas Gampe <agampe@google.com>2016-09-08 15:33:27 -0700
commit2691e335feec4806439054b5c6fe3e7a06cdd695 (patch)
treee85bf607e6eed9c2abcd2fbfbf538713eb046c52
parent88b5af68bd5f272d72aab23e9aedad3ea929fe54 (diff)
downloadcore-2691e335feec4806439054b5c6fe3e7a06cdd695.tar.gz
core-2691e335feec4806439054b5c6fe3e7a06cdd695.tar.bz2
core-2691e335feec4806439054b5c6fe3e7a06cdd695.zip
Base: Add AbortFunction for logging
Add a hook to modify FATAL behavior. Add a test. Bug: 31338270 Test: m Test: mmma system/core/base && $ANDROID_HOST_OUT/nativetest64/libbase_test/libbase_test64 Change-Id: I966da319cda613738b3f2ccdac8c21900d6a5c72
-rw-r--r--base/include/android-base/logging.h24
-rw-r--r--base/logging.cpp27
-rw-r--r--base/logging_test.cpp20
3 files changed, 56 insertions, 15 deletions
diff --git a/base/include/android-base/logging.h b/base/include/android-base/logging.h
index c626fc353..39f468977 100644
--- a/base/include/android-base/logging.h
+++ b/base/include/android-base/logging.h
@@ -51,12 +51,15 @@ enum LogId {
SYSTEM,
};
-typedef std::function<void(LogId, LogSeverity, const char*, const char*,
- unsigned int, const char*)> LogFunction;
+using LogFunction = std::function<void(LogId, LogSeverity, const char*, const char*,
+ unsigned int, const char*)>;
+using AbortFunction = std::function<void(const char*)>;
void KernelLogger(LogId, LogSeverity, const char*, const char*, unsigned int, const char*);
void StderrLogger(LogId, LogSeverity, const char*, const char*, unsigned int, const char*);
+void DefaultAborter(const char* abort_message);
+
#ifdef __ANDROID__
// We expose this even though it is the default because a user that wants to
// override the default log buffer will have to construct this themselves.
@@ -80,15 +83,22 @@ class LogdLogger {
// The tag (or '*' for the global level) comes first, followed by a colon and a
// letter indicating the minimum priority level we're expected to log. This can
// be used to reveal or conceal logs with specific tags.
-void InitLogging(char* argv[], LogFunction&& logger);
-
-// Configures logging using the default logger (logd for the device, stderr for
-// the host).
-void InitLogging(char* argv[]);
+#ifdef __ANDROID__
+#define INIT_LOGGING_DEFAULT_LOGGER LogdLogger()
+#else
+#define INIT_LOGGING_DEFAULT_LOGGER StderrLogger
+#endif
+void InitLogging(char* argv[],
+ LogFunction&& logger = INIT_LOGGING_DEFAULT_LOGGER,
+ AbortFunction&& aborter = DefaultAborter);
+#undef INIT_LOGGING_DEFAULT_LOGGER
// Replace the current logger.
void SetLogger(LogFunction&& logger);
+// Replace the current aborter.
+void SetAborter(AbortFunction&& aborter);
+
class ErrnoRestorer {
public:
ErrnoRestorer()
diff --git a/base/logging.cpp b/base/logging.cpp
index 86d3b4d26..6e1dd9ca3 100644
--- a/base/logging.cpp
+++ b/base/logging.cpp
@@ -173,6 +173,8 @@ static auto& gLogger = *new LogFunction(LogdLogger());
static auto& gLogger = *new LogFunction(StderrLogger);
#endif
+static auto& gAborter = *new AbortFunction(DefaultAborter);
+
static bool gInitialized = false;
static LogSeverity gMinimumLogSeverity = INFO;
static auto& gProgramInvocationName = *new std::unique_ptr<std::string>();
@@ -247,6 +249,15 @@ void StderrLogger(LogId, LogSeverity severity, const char*, const char* file,
severity_char, timestamp, getpid(), GetThreadId(), file, line, message);
}
+void DefaultAborter(const char* abort_message) {
+#ifdef __ANDROID__
+ android_set_abort_message(abort_message);
+#else
+ UNUSED(abort_message);
+#endif
+ abort();
+}
+
#ifdef __ANDROID__
LogdLogger::LogdLogger(LogId default_log_id) : default_log_id_(default_log_id) {
@@ -284,12 +295,10 @@ void LogdLogger::operator()(LogId id, LogSeverity severity, const char* tag,
}
#endif
-void InitLogging(char* argv[], LogFunction&& logger) {
+void InitLogging(char* argv[], LogFunction&& logger, AbortFunction&& aborter) {
SetLogger(std::forward<LogFunction>(logger));
- InitLogging(argv);
-}
+ SetAborter(std::forward<AbortFunction>(aborter));
-void InitLogging(char* argv[]) {
if (gInitialized) {
return;
}
@@ -349,6 +358,11 @@ void SetLogger(LogFunction&& logger) {
gLogger = std::move(logger);
}
+void SetAborter(AbortFunction&& aborter) {
+ lock_guard<mutex> lock(logging_lock);
+ gAborter = std::move(aborter);
+}
+
static const char* GetFileBasename(const char* file) {
// We can't use basename(3) even on Unix because the Mac doesn't
// have a non-modifying basename.
@@ -450,10 +464,7 @@ LogMessage::~LogMessage() {
// Abort if necessary.
if (data_->GetSeverity() == FATAL) {
-#ifdef __ANDROID__
- android_set_abort_message(msg.c_str());
-#endif
- abort();
+ gAborter(msg.c_str());
}
}
diff --git a/base/logging_test.cpp b/base/logging_test.cpp
index 3fde302a3..02a919870 100644
--- a/base/logging_test.cpp
+++ b/base/logging_test.cpp
@@ -330,3 +330,23 @@ TEST(logging, UNIMPLEMENTED) {
UNIMPLEMENTED(ERROR);
CheckMessage(cap, android::base::ERROR, expected.c_str());
}
+
+static void NoopAborter(const char* msg ATTRIBUTE_UNUSED) {
+ LOG(ERROR) << "called noop";
+}
+
+TEST(logging, LOG_FATAL_NOOP_ABORTER) {
+ {
+ android::base::SetAborter(NoopAborter);
+
+ android::base::ScopedLogSeverity sls(android::base::ERROR);
+ CapturedStderr cap;
+ LOG(FATAL) << "foobar";
+ CheckMessage(cap, android::base::FATAL, "foobar");
+ CheckMessage(cap, android::base::ERROR, "called noop");
+
+ android::base::SetAborter(android::base::DefaultAborter);
+ }
+
+ ASSERT_DEATH({SuppressAbortUI(); LOG(FATAL) << "foobar";}, "foobar");
+}