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

Commit 46755e27 authored by Simon MacMullen's avatar Simon MacMullen
Browse files

Log to dropbox if we fail to create an ANR stack trace file.

Some ANRs have no stack traces uploaded through dropbox. This appears to be because the file holding them was not created

So in the case where we can't create the file, add an exception message to the string part of the dropbox upload.

Change-Id: Ic06ac9c25974633905b1a0bfcfcef8ed833795e8
Bug: 148848039
Test: Manually threw exception in createAnrDumpFile() and triggered ANR.
parent 253b3636
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -175,6 +175,6 @@ public class SystemServerInitThreadPool {
        final ArrayList<Integer> pids = new ArrayList<>();
        pids.add(Process.myPid());
        ActivityManagerService.dumpStackTraces(pids, null, null,
                Watchdog.getInterestingNativePids());
                Watchdog.getInterestingNativePids(), null);
    }
}
+9 −4
Original line number Diff line number Diff line
@@ -50,6 +50,7 @@ import com.android.server.wm.SurfaceAnimationThread;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -583,7 +584,7 @@ public class Watchdog extends Thread {
                            ArrayList<Integer> pids = new ArrayList<Integer>();
                            pids.add(Process.myPid());
                            ActivityManagerService.dumpStackTraces(pids, null, null,
                                getInterestingNativePids());
                                    getInterestingNativePids(), null);
                            waitedHalf = true;
                        }
                        continue;
@@ -610,15 +611,19 @@ public class Watchdog extends Thread {

            long anrTime = SystemClock.uptimeMillis();
            ProcessCpuTracker processCpuTracker = new ProcessCpuTracker(false);
            StringWriter tracesFileException = new StringWriter();
            final File stack = ActivityManagerService.dumpStackTraces(
                    pids, processCpuTracker, new SparseArray<>(), getInterestingNativePids());
                    pids, processCpuTracker, new SparseArray<>(), getInterestingNativePids(),
                    tracesFileException);

            // Give some extra time to make sure the stack traces get written.
            // The system's been hanging for a minute, another second or two won't hurt much.
            SystemClock.sleep(5000);

            processCpuTracker.update();
            String cpuInfo = processCpuTracker.printCurrentState(anrTime);
            StringBuilder report = new StringBuilder();
            report.append(processCpuTracker.printCurrentState(anrTime));
            report.append(tracesFileException.getBuffer());

            // Trigger the kernel to dump all blocked threads, and backtraces on all CPUs to the kernel log
            doSysRq('w');
@@ -634,7 +639,7 @@ public class Watchdog extends Thread {
                        if (mActivity != null) {
                            mActivity.addErrorToDropBox(
                                    "watchdog", null, "system_server", null, null, null,
                                    subject, cpuInfo, stack, null);
                                    subject, report.toString(), stack, null);
                        }
                        FrameworkStatsLog.write(FrameworkStatsLog.SYSTEM_SERVER_WATCHDOG_OCCURRED,
                                subject);
+17 −15
Original line number Diff line number Diff line
@@ -3851,10 +3851,11 @@ public class ActivityManagerService extends IActivityManager.Stub
     * @param firstPids of dalvik VM processes to dump stack traces for first
     * @param lastPids of dalvik VM processes to dump stack traces for last
     * @param nativePids optional list of native pids to dump stack crawls
     * @param logExceptionCreatingFile optional writer to which we log errors creating the file
     */
    public static File dumpStackTraces(ArrayList<Integer> firstPids,
            ProcessCpuTracker processCpuTracker, SparseArray<Boolean> lastPids,
            ArrayList<Integer> nativePids) {
            ArrayList<Integer> nativePids, StringWriter logExceptionCreatingFile) {
        ArrayList<Integer> extraPids = null;
        Slog.i(TAG, "dumpStackTraces pids=" + lastPids + " nativepids=" + nativePids);
@@ -3894,8 +3895,15 @@ public class ActivityManagerService extends IActivityManager.Stub
        // NOTE: We should consider creating the file in native code atomically once we've
        // gotten rid of the old scheme of dumping and lot of the code that deals with paths
        // can be removed.
        File tracesFile = createAnrDumpFile(tracesDir);
        if (tracesFile == null) {
        File tracesFile;
        try {
            tracesFile = createAnrDumpFile(tracesDir);
        } catch (IOException e) {
            Slog.w(TAG, "Exception creating ANR dump file:", e);
            if (logExceptionCreatingFile != null) {
                logExceptionCreatingFile.append("----- Exception creating ANR dump file -----\n");
                e.printStackTrace(new PrintWriter(logExceptionCreatingFile));
            }
            return null;
        }
@@ -3906,7 +3914,7 @@ public class ActivityManagerService extends IActivityManager.Stub
    @GuardedBy("ActivityManagerService.class")
    private static SimpleDateFormat sAnrFileDateFormat;
    private static synchronized File createAnrDumpFile(File tracesDir) {
    private static synchronized File createAnrDumpFile(File tracesDir) throws IOException {
        if (sAnrFileDateFormat == null) {
            sAnrFileDateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss-SSS");
        }
@@ -3914,18 +3922,12 @@ public class ActivityManagerService extends IActivityManager.Stub
        final String formattedDate = sAnrFileDateFormat.format(new Date());
        final File anrFile = new File(tracesDir, "anr_" + formattedDate);
        try {
        if (anrFile.createNewFile()) {
            FileUtils.setPermissions(anrFile.getAbsolutePath(), 0600, -1, -1); // -rw-------
            return anrFile;
        } else {
                Slog.w(TAG, "Unable to create ANR dump file: createNewFile failed");
            throw new IOException("Unable to create ANR dump file: createNewFile failed");
        }
        } catch (IOException ioe) {
            Slog.w(TAG, "Exception creating ANR dump file:", ioe);
        }
        return null;
    }
    /**
+9 −5
Original line number Diff line number Diff line
@@ -71,6 +71,7 @@ import com.android.server.wm.WindowProcessListener;

import java.io.File;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -1608,19 +1609,21 @@ class ProcessRecord implements WindowProcessListener {

        // For background ANRs, don't pass the ProcessCpuTracker to
        // avoid spending 1/2 second collecting stats to rank lastPids.
        StringWriter tracesFileException = new StringWriter();
        File tracesFile = ActivityManagerService.dumpStackTraces(firstPids,
                (isSilentAnr()) ? null : processCpuTracker, (isSilentAnr()) ? null : lastPids,
                nativePids);
                nativePids, tracesFileException);

        String cpuInfo = null;
        StringBuilder report = new StringBuilder();
        if (isMonitorCpuUsage()) {
            mService.updateCpuStatsNow();
            synchronized (mService.mProcessCpuTracker) {
                cpuInfo = mService.mProcessCpuTracker.printCurrentState(anrTime);
                report.append(mService.mProcessCpuTracker.printCurrentState(anrTime));
            }
            info.append(processCpuTracker.printCurrentLoad());
            info.append(cpuInfo);
            info.append(report);
        }
        report.append(tracesFileException.getBuffer());

        info.append(processCpuTracker.printCurrentState(anrTime));

@@ -1645,7 +1648,8 @@ class ProcessRecord implements WindowProcessListener {
        final ProcessRecord parentPr = parentProcess != null
                ? (ProcessRecord) parentProcess.mOwner : null;
        mService.addErrorToDropBox("anr", this, processName, activityShortComponentName,
                parentShortComponentName, parentPr, annotation, cpuInfo, tracesFile, null);
                parentShortComponentName, parentPr, annotation, report.toString(), tracesFile,
                null);

        if (mWindowProcessController.appNotResponding(info.toString(), () -> kill("anr",
                ApplicationExitInfo.REASON_ANR, true),
+2 −1
Original line number Diff line number Diff line
@@ -158,7 +158,8 @@ final class InputManagerCallback implements InputManagerService.WindowManagerCal
        }

        final File tracesFile = ActivityManagerService.dumpStackTraces(firstPids,
                null /* processCpuTracker */, null /* lastPids */, nativePids);
                null /* processCpuTracker */, null /* lastPids */, nativePids,
                null /* logExceptionCreatingFile */);
        if (tracesFile != null) {
            tracesFile.renameTo(new File(tracesFile.getParent(), tracesFile.getName() + "_pre"));
        }