在這個進程中運行着近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
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中對應死鎖進程的調用棧。