am 6ab3ea5f: am 147ef944: am 60d1e1a0: Merge "Watchdog: Improvement of debuggability"
* commit '6ab3ea5f48abfd777d5bd18d92acc3bc766f78ce':
Watchdog: Improvement of debuggability
diff --git a/services/java/com/android/server/Watchdog.java b/services/java/com/android/server/Watchdog.java
index 9edfad6..2c5038e 100644
--- a/services/java/com/android/server/Watchdog.java
+++ b/services/java/com/android/server/Watchdog.java
@@ -26,6 +26,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.os.Build;
import android.os.Debug;
import android.os.Handler;
import android.os.Message;
@@ -39,6 +40,8 @@
import android.util.Slog;
import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
@@ -429,11 +432,10 @@
}
// 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";
+ Slog.w(TAG, "WATCHDOG PROBLEM IN SYSTEM SERVER: " + name);
EventLog.writeEvent(EventLogTags.WATCHDOG, name);
ArrayList<Integer> pids = new ArrayList<Integer>();
@@ -468,11 +470,15 @@
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.
+ // Only kill/crash 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);
+ if (!Build.TYPE.equals("user")) {
+ forceCrashDump();
+ } else {
+ Process.killProcess(Process.myPid());
+ System.exit(10);
+ }
} else {
Slog.w(TAG, "Debugger connected: Watchdog is *not* killing the system process");
}
@@ -481,6 +487,50 @@
}
}
+ private void forceCrashDump() {
+ /* Sync file system to flash the data which is written just before the
+ * crash.
+ */
+ java.lang.Process p = null;
+ try {
+ p = Runtime.getRuntime().exec("sync");
+ if (p != null) {
+ // It is not necessary to check the exit code, here.
+ // 'sync' command always succeeds, and this function returns 0.
+ p.waitFor();
+ } else {
+ Slog.e(TAG, "Failed to execute 'sync' command. (no process handle)");
+ }
+ } catch (Exception e) {
+ // This code is an emergency path to crash MUT. The system already
+ // caused fatal error, and then calls this function to create a
+ // crash dump. This function must run the code below to force a
+ // crash, even if the sync command failed.
+ // Therefore, ignore all exceptions, here.
+ Slog.e(TAG, "Failed to execute 'sync' command prior to forcing crash: " + e);
+ } finally {
+ if (p != null) {
+ p.destroy();
+ }
+ }
+
+ FileWriter out = null;
+ try {
+ out = new FileWriter("/proc/sysrq-trigger");
+ out.write("c");
+ } catch (IOException e) {
+ Slog.e(TAG, "Failed to write to sysrq-trigger while triggering crash: " + e);
+ } finally {
+ if (out != null) {
+ try {
+ out.close();
+ } catch (IOException e) {
+ Slog.e(TAG, "Failed to close sysrq-trigger while triggering crash: " + e);
+ }
+ }
+ }
+ }
+
private File dumpKernelStackTraces() {
String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
if (tracesPath == null || tracesPath.length() == 0) {