Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 352a8457 authored by Josh Gao's avatar Josh Gao
Browse files

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
parent 460b336d
Loading
Loading
Loading
Loading
+3 −1
Original line number Original line Diff line number Diff line
@@ -163,6 +163,7 @@ cc_test {
            srcs: [
            srcs: [
                "client/debuggerd_client_test.cpp",
                "client/debuggerd_client_test.cpp",
                "debuggerd_test.cpp",
                "debuggerd_test.cpp",
                "tombstoned_client.cpp",
                "util.cpp"
                "util.cpp"
            ],
            ],
        },
        },
@@ -176,7 +177,8 @@ cc_test {
    ],
    ],


    static_libs: [
    static_libs: [
        "libdebuggerd"
        "libdebuggerd",
        "libc_logging",
    ],
    ],


    local_include_dirs: [
    local_include_dirs: [
+95 −0
Original line number Original line Diff line number Diff line
@@ -36,6 +36,7 @@
#include <cutils/sockets.h>
#include <cutils/sockets.h>
#include <debuggerd/handler.h>
#include <debuggerd/handler.h>
#include <debuggerd/protocol.h>
#include <debuggerd/protocol.h>
#include <debuggerd/tombstoned.h>
#include <debuggerd/util.h>
#include <debuggerd/util.h>
#include <gtest/gtest.h>
#include <gtest/gtest.h>


@@ -525,3 +526,97 @@ TEST(crash_dump, zombie) {
    ASSERT_EQ(0, WEXITSTATUS(status));
    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();
  }
}