OSDN Git Service

ART: Dump more info on 137-cfi failure
authorAndreas Gampe <agampe@google.com>
Mon, 5 Sep 2016 19:30:49 +0000 (12:30 -0700)
committerAndreas Gampe <agampe@google.com>
Tue, 6 Sep 2016 17:57:51 +0000 (10:57 -0700)
Print the maps of the secondary process. Try to induce in-process
dumping of the secondary.

Bug: 31208203
Change-Id: I16a80e8510b297d61a51fdee91ab1c2f2e5a47c8

test/137-cfi/cfi.cc
test/137-cfi/src/Main.java

index 45251b8..9f1499e 100644 (file)
@@ -29,6 +29,7 @@
 
 #include "base/logging.h"
 #include "base/macros.h"
+#include "base/stringprintf.h"
 #include "gc/heap.h"
 #include "gc/space/image_space.h"
 #include "oat_file.h"
@@ -55,7 +56,7 @@ extern "C" JNIEXPORT jboolean JNICALL Java_Main_sleep(JNIEnv*, jobject, jint, jb
   // Keep pausing.
   printf("Going to sleep\n");
   for (;;) {
-    pause();
+    sleep(1);
   }
 }
 
@@ -86,6 +87,19 @@ static bool CheckStack(Backtrace* bt, const std::vector<std::string>& seq) {
 
   return false;
 }
+
+static void MoreErrorInfo(pid_t pid, bool sig_quit_on_fail) {
+  printf("Secondary pid is %d\n", pid);
+
+  PrintFileToLog(StringPrintf("/proc/%d/maps", pid), ERROR);
+
+  if (sig_quit_on_fail) {
+    int res = kill(pid, SIGQUIT);
+    if (res != 0) {
+      PLOG(ERROR) << "Failed to send signal";
+    }
+  }
+}
 #endif
 
 // Currently we have to fall back to our own loader for the boot image when it's compiled PIC
@@ -254,10 +268,20 @@ extern "C" JNIEXPORT jboolean JNICALL Java_Main_unwindOtherProcess(
     result = CheckStack(bt.get(), full_signatrues ? full_seq : seq);
   }
 
+  constexpr bool kSigQuitOnFail = true;
+  if (!result) {
+    MoreErrorInfo(pid, kSigQuitOnFail);
+  }
+
   if (ptrace(PTRACE_DETACH, pid, 0, 0) != 0) {
     PLOG(ERROR) << "Detach failed";
   }
 
+  // If we failed to unwind and induced an ANR dump, give the child some time (20s).
+  if (!result && kSigQuitOnFail) {
+    sleep(20);
+  }
+
   // Kill the other process once we are done with it.
   kill(pid, SIGKILL);
 
index 5cfe33d..1ec7072 100644 (file)
@@ -101,9 +101,10 @@ public class Main implements Comparator<Main> {
           }
 
           // Wait until the forked process had time to run until its sleep phase.
+          BufferedReader lineReader;
           try {
               InputStreamReader stdout = new InputStreamReader(p.getInputStream(), "UTF-8");
-              BufferedReader lineReader = new BufferedReader(stdout);
+              lineReader = new BufferedReader(stdout);
               while (!lineReader.readLine().contains("Going to sleep")) {
               }
           } catch (Exception e) {
@@ -112,6 +113,26 @@ public class Main implements Comparator<Main> {
 
           if (!unwindOtherProcess(fullSignatures, pid)) {
               System.out.println("Unwinding other process failed.");
+
+              // In this case, log all the output.
+              // Note: this is potentially non-terminating code, if the secondary is totally stuck.
+              //       We rely on the run-test timeout infrastructure to terminate the primary in
+              //       such a case.
+              try {
+                  String tmp;
+                  System.out.println("Output from the secondary:");
+                  while ((tmp = lineReader.readLine()) != null) {
+                      System.out.println("Secondary: " + tmp);
+                  }
+              } catch (Exception e) {
+                  e.printStackTrace(System.out);
+              }
+          }
+
+          try {
+              lineReader.close();
+          } catch (Exception e) {
+              e.printStackTrace(System.out);
           }
       } finally {
           // Kill the forked process if it is not already dead.