Ejemplo n.º 1
0
  @Override
  public void run() {
    boolean waitedHalf = false;
    while (true) {
      mCompleted = false;
      mHandler.sendEmptyMessage(MONITOR);
      synchronized (this) {
        long timeout = TIME_TO_WAIT;

        // NOTE: We use uptimeMillis() here because we do not want to increment the time we
        // wait while asleep. If the device is asleep then the thing that we are waiting
        // to timeout on is asleep as well and won't have a chance to run, causing a false
        // positive on when to kill things.
        long start = SystemClock.uptimeMillis();
        while (timeout > 0 && !mForceKillSystem) {
          try {
            wait(timeout); // notifyAll() is called when mForceKillSystem is set
          } catch (InterruptedException e) {
            Log.wtf(TAG, e);
          }
          timeout = TIME_TO_WAIT - (SystemClock.uptimeMillis() - start);
        }

        if (mCompleted && !mForceKillSystem) {
          // The monitors have returned.
          waitedHalf = false;
          continue;
        }

        if (!waitedHalf) {
          // We've waited half the deadlock-detection interval.  Pull a stack
          // trace and wait another half.
          ArrayList<Integer> pids = new ArrayList<Integer>();
          pids.add(Process.myPid());
          ActivityManagerService.dumpStackTraces(true, pids, null, null);
          waitedHalf = true;
          continue;
        }
      }

      // If we got here, that means that the system is most likely hung.
      // First collect stack traces from all threads of the system process.
      // Then kill this process so that the system will restart.

      final String name = (mCurrentMonitor != null) ? mCurrentMonitor.getClass().getName() : "null";
      EventLog.writeEvent(EventLogTags.WATCHDOG, name);

      ArrayList<Integer> pids = new ArrayList<Integer>();
      pids.add(Process.myPid());
      if (mPhonePid > 0) pids.add(mPhonePid);
      // Pass !waitedHalf so that just in case we somehow wind up here without having
      // dumped the halfway stacks, we properly re-initialize the trace file.
      final File stack = ActivityManagerService.dumpStackTraces(!waitedHalf, pids, null, null);

      // 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(2000);

      // Pull our own kernel thread stacks as well if we're configured for that
      if (RECORD_KERNEL_THREADS) {
        dumpKernelStackTraces();
      }

      String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
      if (tracesPath != null && tracesPath.length() != 0) {
        File traceRenameFile = new File(tracesPath);
        String newTracesPath;
        int lpos = tracesPath.lastIndexOf(".");
        if (-1 != lpos)
          newTracesPath =
              tracesPath.substring(0, lpos) + "_SystemServer_WDT" + tracesPath.substring(lpos);
        else newTracesPath = tracesPath + "_SystemServer_WDT";
        traceRenameFile.renameTo(new File(newTracesPath));
        tracesPath = newTracesPath;
      }

      final File newFd = new File(tracesPath);

      // Try to add the error to the dropbox, but assuming that the ActivityManager
      // itself may be deadlocked.  (which has happened, causing this statement to
      // deadlock and the watchdog as a whole to be ineffective)
      Thread dropboxThread =
          new Thread("watchdogWriteToDropbox") {
            public void run() {
              mActivity.addErrorToDropBox(
                  "watchdog", null, "system_server", null, null, name, null, newFd, null);
            }
          };
      dropboxThread.start();
      try {
        dropboxThread.join(2000); // wait up to 2 seconds for it to return.
      } catch (InterruptedException ignored) {
      }

      // Only kill the process if the debugger is not attached.
      if (!Debug.isDebuggerConnected()) {
        if (SystemProperties.getInt("sys.watchdog.disabled", 0) == 0) {
          Process.sendSignal(Process.myPid(), 6);
          SystemClock.sleep(2000);
          Process.sendSignal(Process.myPid(), 6);
          SystemClock.sleep(2000);

          String procs = SystemProperties.get("sys.watchdog.extraprocnames");
          if (procs != null && procs.length() > 0) {
            Slog.w(TAG, "Processes to create tombstones: [" + procs + "]");
            createTombstone(procs);
          } else {
            Slog.w(TAG, "No process is given for creating tombstones on framework reboot.");
          }

          Slog.w(TAG, "*** WATCHDOG KILLING SYSTEM PROCESS: " + name);
          Process.killProcess(Process.myPid());
          System.exit(10);
        } else {
          Slog.w(TAG, "*** WATCHDOG NOT KILLING SYSTEM PROCESS: " + name);
          // Send the SIGSTOP to the System Process for DEBUG purposes
          Process.sendSignal(Process.myPid(), 19);
          break;
        }
      } else {
        Slog.w(TAG, "Debugger connected: Watchdog is *not* killing the system process");
      }

      waitedHalf = false;
    }
  }
Ejemplo n.º 2
0
  @Override
  public void run() {
    boolean waitedHalf = false;
    while (true) {
      mCompleted = false;
      mHandler.sendEmptyMessage(MONITOR);

      synchronized (this) {
        long timeout = TIME_TO_WAIT;

        // NOTE: We use uptimeMillis() here because we do not want to increment the time we
        // wait while asleep. If the device is asleep then the thing that we are waiting
        // to timeout on is asleep as well and won't have a chance to run, causing a false
        // positive on when to kill things.
        long start = SystemClock.uptimeMillis();
        while (timeout > 0 && !mForceKillSystem) {
          try {
            wait(timeout); // notifyAll() is called when mForceKillSystem is set
          } catch (InterruptedException e) {
            Log.wtf(TAG, e);
          }
          timeout = TIME_TO_WAIT - (SystemClock.uptimeMillis() - start);
        }

        if (mCompleted && !mForceKillSystem) {
          // The monitors have returned.
          waitedHalf = false;
          continue;
        }

        if (!waitedHalf) {
          // We've waited half the deadlock-detection interval.  Pull a stack
          // trace and wait another half.
          ArrayList<Integer> pids = new ArrayList<Integer>();

          /// M: WDT debug enhancement:
          /// it's better to dump all running processes backtraces @{
          // pids.add(Process.myPid());
          mActivity.getRunningProcessPids(pids);
          /// @}

          pids.add(Process.myPid());
          ActivityManagerService.dumpStackTraces(true, pids, null, null, NATIVE_STACKS_OF_INTEREST);
          waitedHalf = true;
          continue;
        }
      }

      // If we got here, that means that the system is most likely hung.
      // First collect stack traces from all threads of the system process.
      // Then kill this process so that the system will restart.

      final String name = (mCurrentMonitor != null) ? mCurrentMonitor.getClass().getName() : "null";
      EventLog.writeEvent(EventLogTags.WATCHDOG, name);

      ArrayList<Integer> pids = new ArrayList<Integer>();

      /// M: WDT debug enhancement
      /// it's better to dump all running processes backtraces
      /// and integrate with AEE @{
      /*
      pids.add(Process.myPid());
      if (mPhonePid > 0) pids.add(mPhonePid);
      // Pass !waitedHalf so that just in case we somehow wind up here without having
      // dumped the halfway stacks, we properly re-initialize the trace file.
      final File stack = ActivityManagerService.dumpStackTraces(
              !waitedHalf, pids, null, null, NATIVE_STACKS_OF_INTEREST);
      */
      mActivity.getRunningProcessPids(pids);
      final File stack = dumpAllBackTraces(pids);
      /// @}

      // 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(2000);

      // Pull our own kernel thread stacks as well if we're configured for that
      if (RECORD_KERNEL_THREADS) {
        dumpKernelStackTraces();
      }

      // Trigger the kernel to dump all blocked threads to the kernel log
      try {
        FileWriter sysrq_trigger = new FileWriter("/proc/sysrq-trigger");
        sysrq_trigger.write("w");
        sysrq_trigger.close();
      } catch (IOException e) {
        Slog.e(TAG, "Failed to write to /proc/sysrq-trigger");
        Slog.e(TAG, e.getMessage());
      }

      /// M: WDT debug enhancement
      /// need to wait the AEE dumps all info, then kill system server @{
      /*
      // Try to add the error to the dropbox, but assuming that the ActivityManager
      // itself may be deadlocked.  (which has happened, causing this statement to
      // deadlock and the watchdog as a whole to be ineffective)
      Thread dropboxThread = new Thread("watchdogWriteToDropbox") {
              public void run() {
                  mActivity.addErrorToDropBox(
                          "watchdog", null, "system_server", null, null,
                          name, null, stack, null);
              }
          };
      dropboxThread.start();
      try {
          dropboxThread.join(2000);  // wait up to 2 seconds for it to return.
      } catch (InterruptedException ignored) {}
      */
      Slog.v(TAG, "** save all info before killnig system server **");
      mActivity.addErrorToDropBox(
          "watchdog", null, "system_server", null, null, name, null, null, null);
      SystemClock.sleep(25000);
      /// @}

      // Only kill the process if the debugger is not attached.
      if (!Debug.isDebuggerConnected()) {
        Slog.w(TAG, "*** WATCHDOG KILLING SYSTEM PROCESS: " + name);
        Process.killProcess(Process.myPid());
        System.exit(10);
      } else {
        Slog.w(TAG, "Debugger connected: Watchdog is *not* killing the system process");
      }

      waitedHalf = false;
    }
  }