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
(cherry picked from commit 352a84574d)
This commit is contained in:
Josh Gao 2017-03-30 16:46:21 -07:00
parent df8cb05498
commit dd61876771
2 changed files with 98 additions and 1 deletions

View File

@ -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: [

View File

@ -36,6 +36,7 @@
#include <cutils/sockets.h>
#include <debuggerd/handler.h>
#include <debuggerd/protocol.h>
#include <debuggerd/tombstoned.h>
#include <debuggerd/util.h>
#include <gtest/gtest.h>
@ -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<bool> start(false);
std::vector<std::thread> 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();
}
}