[RESTRICT AUTOMERGE]: Fix a race condition in the crash reporter
problems fixed:
* logcat wasn't cleared before checking for crashes
* unrelated crashes could be reported as part of the current test
* The test could start before the reporter was started
* matching a crash before the test start caused a nullpointerexception
Bug: 162378163
Test: adb shell kill -11 mediaextractor # during run for StagefrightTests
Change-Id: Ie31d1f47c3485808a89c4b33addd303914cb36a4
Merged-In: Ie31d1f47c3485808a89c4b33addd303914cb36a4
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/CrashReporter.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/CrashReporter.java
index c8a7dfe..58133bb 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/CrashReporter.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/CrashReporter.java
@@ -47,6 +47,9 @@
/** Uploads the current buffer of Crashes to the phone under the current test name. */
private static void upload(ITestDevice device, String testname, List<Crash> crashes) {
+ if (crashes == null) {
+ crashes = new ArrayList<>();
+ }
try {
if (testname == null) {
CLog.logAndDisplay(LogLevel.ERROR, "Attempted upload with no test name");
@@ -79,6 +82,13 @@
@Override
public void setUp(ITestDevice device, IBuildInfo buildInfo) {
try {
+ device.executeShellCommand("logcat -c");
+ } catch (DeviceNotAvailableException e) {
+ CLog.logAndDisplay(LogLevel.ERROR, "CrashReporterThread failed to clear logcat");
+ CLog.logAndDisplay(LogLevel.ERROR, e.getMessage());
+ }
+
+ try {
device.executeShellCommand("rm -rf " + CrashUtils.DEVICE_PATH);
device.executeShellCommand("mkdir " + CrashUtils.DEVICE_PATH);
} catch (DeviceNotAvailableException e) {
@@ -88,14 +98,23 @@
CLog.logAndDisplay(LogLevel.ERROR, e.getMessage());
return;
}
+
+ CrashReporterReceiver receiver = new CrashReporterReceiver(device);
mBackgroundThread =
new BackgroundDeviceAction(
- "logcat",
- "CrashReporter logcat thread",
- device,
- new CrashReporterReceiver(device),
- 0);
+ "logcat", "CrashReporter logcat thread", device, receiver, 0);
mBackgroundThread.start();
+
+ try {
+ // If the test starts before the reporter receiver can read the test start message then
+ // the crash could only be read halfway. We wait until the receiver starts getting
+ // messages.
+ synchronized (receiver) {
+ receiver.wait(10_000); // wait for 10 seconds max
+ }
+ } catch (InterruptedException e) {
+ // continue as normal
+ }
}
/** {@inheritDoc} */
@@ -133,6 +152,11 @@
mCrashes = new ArrayList<Crash>();
mLogcatChunk.setLength(0);
} else if (CrashUtils.sEndofCrashPattern.matcher(line).find()) {
+ if (mCrashes == null) {
+ // In case the crash happens before any test is started, it's not related to the
+ // current test and shouldn't be reported.
+ return;
+ }
mCrashes = CrashUtils.getAllCrashes(mLogcatChunk.toString());
mLogcatChunk.setLength(0);
} else if (CrashUtils.sUploadRequestPattern.matcher(line).find()) {
@@ -142,6 +166,7 @@
@Override
public void processNewLines(String[] lines) {
+ this.notifyAll(); // alert the main thread that we are active.
if (!isCancelled()) {
for (String line : lines) {
processLogLine(line);