Limit the number of log messages in a tombstone.

Some testing environments can have a test that is sending many
thousands of messages to the log. When this type of process crashes
all of these log messages are captured and can cause OOM errors
while creating the tombstone.

Added a test to verify the log messages are truncated. Leaving this
test disabled for now since it is inherently flaky due to having to
assume that 500 messages are in the log.

Added a test for a newline in a log message since it's somewhat
related to this change.

NOTE: The total number of messages is capped at 500, but if a message
contains multiple newlines, the total messages will exceed 500.
Counting messages this way seems to be in the spirit of the cap,
that a process logging a large message with multiple newlines does
not completely fill the tombstone log data.

Bug: 269182937
Bug: 282661754

Test: All unit tests pass.
Test: The disabled max_log_messages test passes.
Change-Id: If18e62b29f899c2c4670101b402e37762bffbec6
This commit is contained in:
Christopher Ferris 2023-05-24 20:01:10 +00:00
parent eb8079e656
commit 98d6242dc7
2 changed files with 50 additions and 2 deletions

View file

@ -2759,3 +2759,48 @@ TEST_F(CrasherTest, logd_skips_reading_logs_not_main_thread) {
ASSERT_BACKTRACE_FRAME(result, "raise_debugger_signal");
ASSERT_NOT_MATCH(result, kLogMessage);
}
// Disable this test since there is a high liklihood that this would
// be flaky since it requires 500 messages being in the log.
TEST_F(CrasherTest, DISABLED_max_log_messages) {
StartProcess([]() {
for (size_t i = 0; i < 600; i++) {
LOG(INFO) << "Message number " << i;
}
abort();
});
unique_fd output_fd;
StartIntercept(&output_fd);
FinishCrasher();
AssertDeath(SIGABRT);
int intercept_result;
FinishIntercept(&intercept_result);
ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
std::string result;
ConsumeFd(std::move(output_fd), &result);
ASSERT_NOT_MATCH(result, "Message number 99");
ASSERT_MATCH(result, "Message number 100");
ASSERT_MATCH(result, "Message number 599");
}
TEST_F(CrasherTest, log_with_newline) {
StartProcess([]() {
LOG(INFO) << "This line has a newline.\nThis is on the next line.";
abort();
});
unique_fd output_fd;
StartIntercept(&output_fd);
FinishCrasher();
AssertDeath(SIGABRT);
int intercept_result;
FinishIntercept(&intercept_result);
ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
std::string result;
ConsumeFd(std::move(output_fd), &result);
ASSERT_MATCH(result, ":\\s*This line has a newline.");
ASSERT_MATCH(result, ":\\s*This is on the next line.");
}

View file

@ -70,6 +70,9 @@
using android::base::StringPrintf;
// The maximum number of messages to save in the protobuf per file.
static constexpr size_t kMaxLogMessages = 500;
// Use the demangler from libc++.
extern "C" char* __cxa_demangle(const char*, char*, size_t*, int* status);
@ -491,8 +494,8 @@ static void dump_mappings(Tombstone* tombstone, unwindstack::Maps* maps,
}
static void dump_log_file(Tombstone* tombstone, const char* logger, pid_t pid) {
logger_list* logger_list =
android_logger_list_open(android_name_to_log_id(logger), ANDROID_LOG_NONBLOCK, 0, pid);
logger_list* logger_list = android_logger_list_open(android_name_to_log_id(logger),
ANDROID_LOG_NONBLOCK, kMaxLogMessages, pid);
LogBuffer buffer;