From 352a84574dd0f3be0c30d15c0c577c226ec28c2f Mon Sep 17 00:00:00 2001 From: Josh Gao Date: Thu, 30 Mar 2017 16:46:21 -0700 Subject: [PATCH] tombstoned: add tests for b/36685795. Add some tests for edge cases which may have triggered b/36685795. Bug: http://b/36685795 Test: debuggerd_test Change-Id: I20670684c8dae422af157be21e44ba5d6d3214d3 --- debuggerd/Android.bp | 4 +- debuggerd/debuggerd_test.cpp | 95 ++++++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+), 1 deletion(-) diff --git a/debuggerd/Android.bp b/debuggerd/Android.bp index 024bc3d03..4783d6e56 100644 --- a/debuggerd/Android.bp +++ b/debuggerd/Android.bp @@ -163,6 +163,7 @@ cc_test { srcs: [ "client/debuggerd_client_test.cpp", "debuggerd_test.cpp", + "tombstoned_client.cpp", "util.cpp" ], }, @@ -176,7 +177,8 @@ cc_test { ], static_libs: [ - "libdebuggerd" + "libdebuggerd", + "libc_logging", ], local_include_dirs: [ diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp index 410c4ae59..1befcb190 100644 --- a/debuggerd/debuggerd_test.cpp +++ b/debuggerd/debuggerd_test.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -525,3 +526,97 @@ TEST(crash_dump, zombie) { ASSERT_EQ(0, WEXITSTATUS(status)); } } + +TEST(tombstoned, no_notify) { + // Do this a few times. + for (int i = 0; i < 3; ++i) { + pid_t pid = 123'456'789 + i; + + unique_fd intercept_fd, output_fd; + tombstoned_intercept(pid, &intercept_fd, &output_fd); + + { + unique_fd tombstoned_socket, input_fd; + ASSERT_TRUE(tombstoned_connect(pid, &tombstoned_socket, &input_fd)); + ASSERT_TRUE(android::base::WriteFully(input_fd.get(), &pid, sizeof(pid))); + } + + pid_t read_pid; + ASSERT_TRUE(android::base::ReadFully(output_fd.get(), &read_pid, sizeof(read_pid))); + ASSERT_EQ(read_pid, pid); + } +} + +TEST(tombstoned, stress) { + // Spawn threads to simultaneously do a bunch of failing dumps and a bunch of successful dumps. + static constexpr int kDumpCount = 100; + + std::atomic start(false); + std::vector threads; + threads.emplace_back([&start]() { + while (!start) { + continue; + } + + // Use a way out of range pid, to avoid stomping on an actual process. + pid_t pid_base = 1'000'000; + + for (int dump = 0; dump < kDumpCount; ++dump) { + pid_t pid = pid_base + dump; + + unique_fd intercept_fd, output_fd; + tombstoned_intercept(pid, &intercept_fd, &output_fd); + + // Pretend to crash, and then immediately close the socket. + unique_fd sockfd(socket_local_client(kTombstonedCrashSocketName, + ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_SEQPACKET)); + if (sockfd == -1) { + FAIL() << "failed to connect to tombstoned: " << strerror(errno); + } + TombstonedCrashPacket packet = {}; + packet.packet_type = CrashPacketType::kDumpRequest; + packet.packet.dump_request.pid = pid; + if (TEMP_FAILURE_RETRY(write(sockfd, &packet, sizeof(packet))) != sizeof(packet)) { + FAIL() << "failed to write to tombstoned: " << strerror(errno); + } + + continue; + } + }); + + threads.emplace_back([&start]() { + while (!start) { + continue; + } + + // Use a way out of range pid, to avoid stomping on an actual process. + pid_t pid_base = 2'000'000; + + for (int dump = 0; dump < kDumpCount; ++dump) { + pid_t pid = pid_base + dump; + + unique_fd intercept_fd, output_fd; + tombstoned_intercept(pid, &intercept_fd, &output_fd); + + { + unique_fd tombstoned_socket, input_fd; + ASSERT_TRUE(tombstoned_connect(pid, &tombstoned_socket, &input_fd)); + ASSERT_TRUE(android::base::WriteFully(input_fd.get(), &pid, sizeof(pid))); + tombstoned_notify_completion(tombstoned_socket.get()); + } + + // TODO: Fix the race that requires this sleep. + std::this_thread::sleep_for(50ms); + + pid_t read_pid; + ASSERT_TRUE(android::base::ReadFully(output_fd.get(), &read_pid, sizeof(read_pid))); + ASSERT_EQ(read_pid, pid); + } + }); + + start = true; + + for (std::thread& thread : threads) { + thread.join(); + } +}