android sw watchdog and How to Debug

Android 平臺實現了一個軟件的WatchDog來監護SystemServer。SystemServer無疑是Android平臺中最重要的進程了,裏面運行了整個平臺中絕大多數的服務。
在這個進程中運行着近50個線程,任何一個線程死掉都可能導致整個系統死掉。SystemServer退出反而問題不大,因爲 init進程會重新啓動它,但是它死鎖就麻煩了,因爲整個系統就沒法動了。
在 SystemServer裏運行的服務中有很多的服務,具體可以在
framework/base/services/java/com/android/SystemServer中找到
最重要的幾個服務應該數ActivityManager、WindowManager和 PowerManager。

軟件的WatchDog主要就是確保這幾個服務發生死鎖之後,退出SystemServer進程,讓init進程重啓它,讓系統回到可用狀態。


如何在service中添加watchDog?


以WindowManagerServeice爲例, 


首先在構造函數中把自身加入到watchdog monitor服務中:


private WindowManagerService(Context context, PowerManagerService pm,
            boolean haveInputMethods) {
.............
 // Add ourself to the Watchdog monitors.
  Watchdog.getInstance().addMonitor(this);


}


然後每個被監護的Service必須實現Watchdog.Monitor接口,這個接口只要實現一個函數monitor,這個函數實現非常簡單:


// Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection).
    public void monitor() {
        synchronized (mWindowMap) { }
        synchronized (mKeyguardTokenWatcher) { }
    }
 它去鎖一下對象,什麼也不做,然後就返回。如果對象沒有死鎖,這個過程就會很順利。如果對象死鎖了,這個函數就會掛在這裏。


WatchDog如何工作?



在WatchDog啓動之後,開始跑run函數。該函數內部爲一個無限循環。
public void run() {
        boolean waitedHalf = false;
        while (true) {
            mCompleted = false;
            mHandler.sendEmptyMessage(MONITOR);------發送MESSAGE由HeartbeatHandler處理監控的各個對象的狀態
            ...
            while (timeout > 0 && !mForceKillSystem) {
                    try {
                        wait(timeout); ----等待HeartbeatHandler處理結果
                        } catch (InterruptedException e) {
                    }
                    timeout = TIME_TO_WAIT - (SystemClock.uptimeMillis() - start);
                    //TIME_TO_WAIT的默認時間爲30s。此爲第一次等待時間,WatchDog判斷對象是否死鎖的最長處理時間爲1Min。
                }
            
                
        }
}
一開始就會發送一個MONITOR的Message,由HeartbeatHandler負責接收並處理。同時會等待30秒,等待HeartbeatHandler的處理結果。然後纔會進行下一步動作。
在HeartbeatHandler中將會作如下處理:
public void handleMessage(Message msg) {
            switch (msg.what) {
                case MONITOR: {
                ...
                final int size = mMonitors.size();
                    for (int i = 0 ; i < size ; i++) {
                        mCurrentMonitor = mMonitors.get(i);
                        mCurrentMonitor.monitor();
                    }//依次去調用監護對象的monitor接口,實現對其的監護。
                 synchronized (Watchdog.this) {
                        mCompleted = true;
                        mCurrentMonitor = null;
                    }//如果監護的對象都正常,則會很快運行到這裏,並對mCompleted賦值爲true,表示對象正常返回。mCompleted值初始爲false。
    ...}
  }
}




同時在run函數中:if (mCompleted && !mForceKillSystem) {
                    // The monitors have returned.
                    waitedHalf = false;
                    continue;
                   }//如果所有對象在30s內能夠返回,則會得到mCompleted = true;則本次監護就結束,返回繼續下一輪監護。



如果在30s內,monitor對象未能返回,mCompleted 值即爲false,則會運行到run方法中該語句:


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);.....dump出trace文件,將有助於我們對watchdog問題的解決
                    waitedHalf = true;
                    continue;
                }


然後跳出該循環,繼續一輪循環就將會走到run方法如下語句,非死鎖是不會走到的:


// If we got here, that means that the system is most likely hung.


            final String name = (mCurrentMonitor != null) ?
                    mCurrentMonitor.getClass().getName() : "null";
if (!Debug.isDebuggerConnected()) {
                if (Build.TYPE.equals("eng") || Build.TYPE.equals("userdebug")) {
                    Slog.w(TAG, "*** WATCHDOG KILLING THE SYSTEM: " + name);...............發生watchdog的重要LOG


                    // Give some extra time to make sure CrashMonitorService reacts to
                    // the dropbox entry before the crash
                    SystemClock.sleep(2000);


                    forceCrashDump();
                } else {
                    Slog.w(TAG, "*** WATCHDOG KILLING SYSTEM PROCESS: " + name);
                    Process.killProcess(Process.myPid());
                    System.exit(10);
                }



watchdog 的類型:



1:android.server.ServerThread被block,LOG如下:  

02:06:22.571 W/Watchdog( 307): *** WATCHDOG KILLING THE SYSTEM: null


2:諸如windowManagerService ,activityManagerService等死鎖,LOG如下:
02:06:22.571 W/Watchdog( 307): *** WATCHDOG KILLING THE SYSTEM: activityManagerService


如何DEBUG watchdog?


第一種類型的watchdog,我們要首先看trace.txt中serverThread的調用棧. 爲什麼呢?
因爲system server啓動服務 要分兩個過程, 一個是init1()和 init2(),
前者是啓動native service, 比如:surfaceFlinger, AudioFlinger...
後者就是啓動android services, 比如: activityManager, WindowManager...
而啓動android services是在serverThread中進行,代碼如下:


public static final void init2() {
        Slog.i(TAG, "Entered the Android system server!");
        Thread thr = new ServerThread();
        thr.setName("android.server.ServerThread");
        thr.start();
    }
其次,如果遇到調用了native的代碼,就可以用gdb或者crash繼續debug.


第二種類型 看trace.txt中對應死鎖進程的調用棧。
發佈了32 篇原創文章 · 獲贊 59 · 訪問量 44萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章