2525import android .content .Context ;
2626import android .content .Intent ;
2727import android .content .IntentFilter ;
28+ import android .os .Build ;
2829import android .os .Debug ;
2930import android .os .Handler ;
3031import android .os .Message ;
3839import android .util .Slog ;
3940
4041import java .io .File ;
42+ import java .io .FileWriter ;
43+ import java .io .IOException ;
4144import java .util .ArrayList ;
4245import java .util .Calendar ;
4346
@@ -428,11 +431,10 @@ public void run() {
428431 }
429432
430433 // If we got here, that means that the system is most likely hung.
431- // First collect stack traces from all threads of the system process.
432- // Then kill this process so that the system will restart.
433434
434435 final String name = (mCurrentMonitor != null ) ?
435436 mCurrentMonitor .getClass ().getName () : "null" ;
437+ Slog .w (TAG , "WATCHDOG PROBLEM IN SYSTEM SERVER: " + name );
436438 EventLog .writeEvent (EventLogTags .WATCHDOG , name );
437439
438440 ArrayList <Integer > pids = new ArrayList <Integer >();
@@ -467,11 +469,15 @@ public void run() {
467469 dropboxThread .join (2000 ); // wait up to 2 seconds for it to return.
468470 } catch (InterruptedException ignored ) {}
469471
470- // Only kill the process if the debugger is not attached.
472+ // Only kill/crash the process if the debugger is not attached.
471473 if (!Debug .isDebuggerConnected ()) {
472474 Slog .w (TAG , "*** WATCHDOG KILLING SYSTEM PROCESS: " + name );
473- Process .killProcess (Process .myPid ());
474- System .exit (10 );
475+ if (!Build .TYPE .equals ("user" )) {
476+ forceCrashDump ();
477+ } else {
478+ Process .killProcess (Process .myPid ());
479+ System .exit (10 );
480+ }
475481 } else {
476482 Slog .w (TAG , "Debugger connected: Watchdog is *not* killing the system process" );
477483 }
@@ -480,6 +486,50 @@ public void run() {
480486 }
481487 }
482488
489+ private void forceCrashDump () {
490+ /* Sync file system to flash the data which is written just before the
491+ * crash.
492+ */
493+ java .lang .Process p = null ;
494+ try {
495+ p = Runtime .getRuntime ().exec ("sync" );
496+ if (p != null ) {
497+ // It is not necessary to check the exit code, here.
498+ // 'sync' command always succeeds, and this function returns 0.
499+ p .waitFor ();
500+ } else {
501+ Slog .e (TAG , "Failed to execute 'sync' command. (no process handle)" );
502+ }
503+ } catch (Exception e ) {
504+ // This code is an emergency path to crash MUT. The system already
505+ // caused fatal error, and then calls this function to create a
506+ // crash dump. This function must run the code below to force a
507+ // crash, even if the sync command failed.
508+ // Therefore, ignore all exceptions, here.
509+ Slog .e (TAG , "Failed to execute 'sync' command prior to forcing crash: " + e );
510+ } finally {
511+ if (p != null ) {
512+ p .destroy ();
513+ }
514+ }
515+
516+ FileWriter out = null ;
517+ try {
518+ out = new FileWriter ("/proc/sysrq-trigger" );
519+ out .write ("c" );
520+ } catch (IOException e ) {
521+ Slog .e (TAG , "Failed to write to sysrq-trigger while triggering crash: " + e );
522+ } finally {
523+ if (out != null ) {
524+ try {
525+ out .close ();
526+ } catch (IOException e ) {
527+ Slog .e (TAG , "Failed to close sysrq-trigger while triggering crash: " + e );
528+ }
529+ }
530+ }
531+ }
532+
483533 private File dumpKernelStackTraces () {
484534 String tracesPath = SystemProperties .get ("dalvik.vm.stack-trace-file" , null );
485535 if (tracesPath == null || tracesPath .length () == 0 ) {
0 commit comments