Automatically disable isolation when debugging am: 5ac6f0da43 am: 784ba74781 am: a365fadc4b am: d5e9bd1267

Original change: https://android-review.googlesource.com/c/platform/system/testing/gtest_extras/+/1393488

Change-Id: Ib2a6f32903cb133714b7dbb2f0b5552d3bb6e106
diff --git a/IsolateMain.cpp b/IsolateMain.cpp
index bffdee9..9c368b3 100644
--- a/IsolateMain.cpp
+++ b/IsolateMain.cpp
@@ -15,11 +15,14 @@
  */
 
 #include <errno.h>
+#include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
+#include <cstring>
+#include <string_view>
 #include <vector>
 
 #include <gtest/gtest.h>
@@ -43,7 +46,15 @@
       "      Use isolation mode, Run each test in a separate process.\n"
       "      If JOB_COUNT is not given, it is set to the count of available processors.\n");
   ColoredPrintf(COLOR_GREEN, "  --no_isolate\n");
-  printf("      Don't use isolation mode, run all tests in a single process.\n");
+  printf(
+      "      Don't use isolation mode, run all tests in a single process.\n"
+      "      If the test seems to be running in a debugger (based on the parent's name) this will\n"
+      "      be automatically set. If this behavior is not desired use the '--force_isolate' flag\n"
+      "      below.\n");
+  ColoredPrintf(COLOR_GREEN, "  --force_isolate\n");
+  printf(
+      "      Force the use of isolation mode, even if it looks like we are running in a\n"
+      "      debugger.\n");
   ColoredPrintf(COLOR_GREEN, "  --deadline_threshold_ms=");
   ColoredPrintf(COLOR_YELLOW, "[TIME_IN_MS]\n");
   printf("      Run each test in no longer than ");
@@ -76,13 +87,35 @@
 
 static bool RunInIsolationMode(std::vector<const char*>& args) {
   // Parse arguments that can't be used in isolation mode.
+  bool isolation_forced = false;
   for (size_t i = 1; i < args.size(); ++i) {
     if (strcmp(args[i], "--no_isolate") == 0) {
       return false;
+    } else if (strcmp(args[i], "--force_isolate") == 0) {
+      // We want to make sure we prioritize --no_isolate and --gtest_list_tests.
+      isolation_forced = true;
     } else if (strcmp(args[i], "--gtest_list_tests") == 0) {
       return false;
     }
   }
+  if (!isolation_forced) {
+    // Check if we are running gdb/gdbserver. No need to be sneaky we are assuming no one is hiding.
+    pid_t ppid = getppid();
+    std::string exe_path = std::string("/proc/") + std::to_string(ppid) + "/exe";
+    char buf[PATH_MAX + 1];
+    size_t len;
+    // NB We can't use things like android::base::* or std::filesystem::* due to linking
+    // issues.
+    // Since PATH_MAX is the longest a symlink can be in posix we don't need to
+    // deal with truncation. Anyway this isn't critical for correctness and is
+    // just a QOL thing so it's fine if we are wrong.
+    if ((len = TEMP_FAILURE_RETRY(readlink(exe_path.c_str(), buf, sizeof(buf) - 1))) > 0) {
+      buf[len] = '\0';
+      std::string_view file(basename(buf));
+      return file != "gdb" && file != "gdbserver" && file != "gdbserver64" && file != "gdbserver32";
+    }
+    // If we can't figure out what our parent was just assume we are fine to isolate.
+  }
   return true;
 }