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

Commit 5b88a2fd authored by Dianne Hackborn's avatar Dianne Hackborn
Browse files

Debugging help for issue #8734824: WATCHDOG KILLING SYSTEM PROCESS

IActivityController has a new callback which the Watchdog calls
when it detects that the system process is hung.  This may be
use full monkey.  All hail the monkey!

Also add a new private feature to Binder to be able to turn off
all incoming dump() calls to a process.  The watchdog uses this
when it reports it is hung, so that if someone, say, wants to
collect a bug report at this point they won't get stuck waiting
for things that are all busted.

Change-Id: Ib514d97451cf3b93f29e194c1954e29f948c13b1
parent 996f6b04
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -1093,6 +1093,18 @@ public class Am extends BaseCommand {
            }
        }

        @Override
        public int systemNotResponding(String message)
                throws RemoteException {
            synchronized (this) {
                System.out.println("** ERROR: PROCESS NOT RESPONDING");
                System.out.println("message: " + message);
                System.out.println("#");
                System.out.println("Allowing system to die.");
                return -1;
            }
        }

        void killGdbLocked() {
            mGotGdbPrint = false;
            if (mGdbProcess != null) {
+7 −0
Original line number Diff line number Diff line
@@ -58,4 +58,11 @@ interface IActivityController
     * immediately.
     */
    int appNotResponding(String processName, int pid, String processStats);

    /**
     * The system process watchdog has detected that the system seems to be
     * hung.  Return 1 to continue waiting, or -1 to let it continue with its
     * normal kill.
     */
    int systemNotResponding(String msg);
}
+31 −2
Original line number Diff line number Diff line
@@ -49,6 +49,11 @@ public class Binder implements IBinder {
    private static final boolean FIND_POTENTIAL_LEAKS = false;
    private static final String TAG = "Binder";

    /**
     * Control whether dump() calls are allowed.
     */
    private static String sDumpDisabled = null;

    /* mObject is used by native code, do not remove or rename */
    private int mObject;
    private IInterface mOwner;
@@ -225,6 +230,22 @@ public class Binder implements IBinder {
        return null;
    }

    /**
     * Control disabling of dump calls in this process.  This is used by the system
     * process watchdog to disable incoming dump calls while it has detecting the system
     * is hung and is reporting that back to the activity controller.  This is to
     * prevent the controller from getting hung up on bug reports at this point.
     * @hide
     *
     * @param msg The message to show instead of the dump; if null, dumps are
     * re-enabled.
     */
    public static void setDumpDisabled(String msg) {
        synchronized (Binder.class) {
            sDumpDisabled = msg;
        }
    }

    /**
     * Default implementation is a stub that returns false.  You will want
     * to override this to do the appropriate unmarshalling of transactions.
@@ -269,7 +290,15 @@ public class Binder implements IBinder {
        FileOutputStream fout = new FileOutputStream(fd);
        PrintWriter pw = new PrintWriter(fout);
        try {
            final String disabled;
            synchronized (Binder.class) {
                disabled = sDumpDisabled;
            }
            if (disabled == null) {
                dump(fd, pw, args);
            } else {
                pw.println(sDumpDisabled);
            }
        } finally {
            pw.flush();
        }
+29 −0
Original line number Diff line number Diff line
@@ -16,6 +16,9 @@

package com.android.server;

import android.app.IActivityController;
import android.os.Binder;
import android.os.RemoteException;
import com.android.server.am.ActivityManagerService;
import com.android.server.power.PowerManagerService;

@@ -91,6 +94,7 @@ public class Watchdog extends Thread {
    Monitor mCurrentMonitor;

    int mPhonePid;
    IActivityController mController;

    final Calendar mCalendar = Calendar.getInstance();
    int mMinScreenOff = MEMCHECK_DEFAULT_MIN_SCREEN_OFF;
@@ -223,6 +227,12 @@ public class Watchdog extends Thread {
        }
    }

    public void setActivityController(IActivityController controller) {
        synchronized (this) {
            mController = controller;
        }
    }

    public void addMonitor(Monitor monitor) {
        synchronized (this) {
            if (isAlive()) {
@@ -476,6 +486,25 @@ public class Watchdog extends Thread {
                dropboxThread.join(2000);  // wait up to 2 seconds for it to return.
            } catch (InterruptedException ignored) {}

            IActivityController controller;
            synchronized (this) {
                controller = mController;
            }
            if (controller != null) {
                Slog.i(TAG, "Reporting stuck state to activity controller");
                try {
                    Binder.setDumpDisabled("Service dumps disabled due to hung system process.");
                    // 1 = keep waiting, -1 = kill system
                    int res = controller.systemNotResponding(name);
                    if (res >= 0) {
                        Slog.i(TAG, "Activity controller requested to coninue to wait");
                        waitedHalf = false;
                        continue;
                    }
                } catch (RemoteException e) {
                }
            }

            // Only kill the process if the debugger is not attached.
            if (!Debug.isDebuggerConnected()) {
                Slog.w(TAG, "*** WATCHDOG KILLING SYSTEM PROCESS: " + name);
+6 −0
Original line number Diff line number Diff line
@@ -2822,6 +2822,7 @@ public final class ActivityManagerService extends ActivityManagerNative
                        resumeOK = mController.activityResuming(next.packageName);
                    } catch (RemoteException e) {
                        mController = null;
                        Watchdog.getInstance().setActivityController(null);
                    }
    
                    if (!resumeOK) {
@@ -3334,6 +3335,7 @@ public final class ActivityManagerService extends ActivityManagerNative
                if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
            } catch (RemoteException e) {
                mController = null;
                Watchdog.getInstance().setActivityController(null);
            }
        }
@@ -3437,6 +3439,7 @@ public final class ActivityManagerService extends ActivityManagerNative
                }
            } catch (RemoteException e) {
                mController = null;
                Watchdog.getInstance().setActivityController(null);
            }
        }
@@ -7441,6 +7444,7 @@ public final class ActivityManagerService extends ActivityManagerNative
                "setActivityController()");
        synchronized (this) {
            mController = controller;
            Watchdog.getInstance().setActivityController(controller);
        }
    }
@@ -8832,6 +8836,7 @@ public final class ActivityManagerService extends ActivityManagerNative
                    }
                } catch (RemoteException e) {
                    mController = null;
                    Watchdog.getInstance().setActivityController(null);
                }
            }
@@ -12765,6 +12770,7 @@ public final class ActivityManagerService extends ActivityManagerNative
                        resumeOK = mController.activityResuming(next.packageName);
                    } catch (RemoteException e) {
                        mController = null;
                        Watchdog.getInstance().setActivityController(null);
                    }
                    if (!resumeOK) {