Index: chrome/android/java/src/org/chromium/chrome/browser/crash/LogcatExtractionCallable.java |
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/crash/LogcatExtractionCallable.java b/chrome/android/java/src/org/chromium/chrome/browser/crash/LogcatExtractionCallable.java |
index 281708669fbd1ac10d7091decfcc20c0b49207d7..93fbff07809779d67c4460bf0cd608ca5ad4a64f 100644 |
--- a/chrome/android/java/src/org/chromium/chrome/browser/crash/LogcatExtractionCallable.java |
+++ b/chrome/android/java/src/org/chromium/chrome/browser/crash/LogcatExtractionCallable.java |
@@ -90,6 +90,9 @@ public class LogcatExtractionCallable implements Callable<Boolean> { |
protected static final String BEGIN_MICRODUMP = "-----BEGIN BREAKPAD MICRODUMP-----"; |
@VisibleForTesting |
protected static final String END_MICRODUMP = "-----END BREAKPAD MICRODUMP-----"; |
+ @VisibleForTesting |
+ protected static final String SNIPPED_MICRODUMP = |
+ "-----SNIPPED OUT BREAKPAD MICRODUMP FOR THIS CRASH-----"; |
@VisibleForTesting |
protected static final String IP_ELISION = "1.2.3.4"; |
@@ -230,41 +233,37 @@ public class LogcatExtractionCallable implements Callable<Boolean> { |
@VisibleForTesting |
protected List<String> getLogcat() throws IOException, InterruptedException { |
- return getLogcatInternal(); |
- } |
- |
- private static List<String> getLogcatInternal() throws IOException, InterruptedException { |
- List<String> rawLogcat = null; |
+ // Grab the last lines of the logcat output, with a generous buffer to compensate for any |
+ // microdumps that might be in the logcat output, since microdumps are stripped in the |
+ // extraction code. |
+ Process p = Runtime.getRuntime().exec("logcat -d | tail -n " + (LOGCAT_SIZE * 4)); |
Integer exitValue = null; |
- // In the absence of the android.permission.READ_LOGS permission the |
- // the logcat call will just hang. |
- Process p = Runtime.getRuntime().exec("logcat -d"); |
- BufferedReader reader = null; |
- try { |
- reader = new BufferedReader(new InputStreamReader(p.getInputStream())); |
- while (exitValue == null) { |
- rawLogcat = extractLogcatFromReader(reader, LOGCAT_SIZE); |
- try { |
- exitValue = p.exitValue(); |
- } catch (IllegalThreadStateException itse) { |
- Thread.sleep(HALF_SECOND); |
- } |
- } |
- if (exitValue != 0) { |
- String msg = "Logcat failed: " + exitValue; |
- Log.w(TAG, msg); |
- throw new IOException(msg); |
+ while (exitValue == null) { |
+ try { |
+ exitValue = p.exitValue(); |
+ } catch (IllegalThreadStateException itse) { |
+ Thread.sleep(HALF_SECOND); |
} |
- return rawLogcat; |
+ } |
+ if (exitValue != 0) { |
+ String msg = "Logcat failed: " + exitValue; |
+ Log.w(TAG, msg); |
+ throw new IOException(msg); |
+ } |
+ |
+ BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream())); |
+ try { |
+ return extractLogcatFromReader(reader, LOGCAT_SIZE); |
} finally { |
- if (reader != null) { |
- reader.close(); |
- } |
+ reader.close(); |
} |
} |
/** |
- * Extract microdump-free logcat for more informative crash reports |
+ * Extracts microdump-free logcat for more informative crash reports. Returns the most recent |
+ * lines that are likely to be relevant to the crash, which are either the lines leading up to a |
+ * microdump if a microdump is present, or just the final lines of the logcat if no microdump is |
+ * present. |
* |
* @param reader A buffered reader from which lines of initial logcat is read. |
* @param maxLines The maximum number of lines logcat extracts from minidump. |
@@ -275,33 +274,29 @@ public class LogcatExtractionCallable implements Callable<Boolean> { |
@VisibleForTesting |
protected static List<String> extractLogcatFromReader( |
BufferedReader reader, int maxLines) throws IOException { |
- return extractLogcatFromReaderInternal(reader, maxLines); |
- } |
- |
- private static List<String> extractLogcatFromReaderInternal( |
- BufferedReader reader, int maxLines) throws IOException { |
- boolean inMicrodump = false; |
+ // Slurp all of the lines. |
List<String> rawLogcat = new LinkedList<>(); |
String logLn; |
- while ((logLn = reader.readLine()) != null && rawLogcat.size() < maxLines) { |
- if (logLn.contains(BEGIN_MICRODUMP)) { |
- // If the log contains two begin markers without an end marker |
- // in between, we ignore the second begin marker. |
- inMicrodump = true; |
- } else if (logLn.contains(END_MICRODUMP)) { |
- if (!inMicrodump) { |
- // If we have been extracting microdump the whole time, |
- // start over with a clean logcat. |
- rawLogcat.clear(); |
- } else { |
- inMicrodump = false; |
- } |
- } else { |
- if (!inMicrodump) { |
- rawLogcat.add(logLn); |
- } |
+ while ((logLn = reader.readLine()) != null) { |
+ rawLogcat.add(logLn); |
+ } |
+ |
+ // Trim off the last microdump, and anything after it. |
+ for (int i = rawLogcat.size() - 1; i >= 0; i--) { |
+ if (rawLogcat.get(i).contains(BEGIN_MICRODUMP)) { |
+ rawLogcat = rawLogcat.subList(0, i); |
+ rawLogcat.add(SNIPPED_MICRODUMP); |
+ break; |
} |
} |
+ |
+ // Trim down the remainder to only contain the most recent lines. Thus, if the original |
+ // input contained a microdump, the result contains the most recent lines before the |
+ // microdump, which are most likely to be relevant to the crash. If there is no microdump |
+ // in the raw logcat, then just hope that the last lines in the dump are relevant. |
+ if (rawLogcat.size() > maxLines) { |
+ rawLogcat = rawLogcat.subList(rawLogcat.size() - maxLines, rawLogcat.size()); |
+ } |
return rawLogcat; |
} |