サービス アプリへのすべての RPC (プロバイダーまたは aidl) 呼び出しがブロックされるという問題が発生しました。
クライアントが呼び出す関数は単純なので、何時間もブロックされることはないと確信しています (デッドロックはありません)。
バインダードライバーに飛び込み、/sys/kernel/debug/binder に情報を見つけました。
-bidner/stats.txt から、「準備完了」のバインダー スレッドが見つかりませんでした:
proc 918
threads: 23
requested threads: 0+15/15
ready threads 0
-バインダー/プロセス/918 から、いくつかの受信トランザクションと保留中のトランザクションが見つかりました。-anr情報から、カーネルのCPU使用率が高いことがわかりました
CPU usage from 6506ms to 225ms ago:
90% 918/com.evideostb.cbb.cbbship: 4.1% user + 86% kernel / faults: 11165203 minor
CPU usage from 3444ms to 3956ms later:
100% 918/com.evideostb.cbb.cbbship: 0% user + 100% kernel / faults: 1001251 minor
100% 977/Thread-35507: 0% user + 100% kernel
-android-studioを介してandroidプロセスにデバッガーをアタッチしようとすると、まだpsを実行できるにもかかわらず、プロセスがandroid-studioに表示されないことがわかりました。
- gdb を試して、スレッドがすべての情報を適用し、多くのスレッド (またはすべて Java スレッド) が次のようにスタックを印刷します (無限のように見えます):
#0 0xb6e45968 in syscall () from G:\kdroid\tmp\lib\libc.so
#1 0xb4ff76a6 in art::ConditionVariable::Wait(art::Thread*) ()
from G:\kdroid\tmp\lib\libart.so
#2 0xb4ff76a6 in art::ConditionVariable::Wait(art::Thread*) ()
from G:\kdroid\tmp\lib\libart.so
#3 0xb4ff76a6 in art::ConditionVariable::Wait(art::Thread*) ()
from G:\kdroid\tmp\lib\libart.so
......
JDWP スレッド スタックが見つかりません
スレッド 35507 が見つかりません
このアプリは複雑すぎてすべてのコードをここに置くことはできません。参照コードを貼り付けてください。
-サービス:
public void onCreate() {
super.onCreate();
Notification notification = new Notification();
notification.flags = notification.flags
| Notification.FLAG_NO_CLEAR;
startForeground(
getClass().hashCode(),
notification);
}
-OnBind は次のように戻ります:
interface ICbbServiceBinder{
IBinder getCbbService(int serviceEnumOrdinal);
}
埋め込む:
private static SparseArray<IBinder> mBinders = new SparseArray<>();
public static IBinder getFunction(CbbClient.ServiceName name){
return mBinders.get(name.ordinal());
}
-クライアント側:
private final SparseArray<IInterface> mCache = new SparseArray<>();
public IInterface getService(ServiceName name){
if (!mIsInit){
Log.e(TAG, "getService: cbb remote server down");
return null;
}
int nameOrdinal = name.ordinal();
synchronized (mCache) {
IInterface iInterface = mCache.get(nameOrdinal);
if (iInterface == null) {
IBinder binder;
try {
binder = mCbbServer.getCbbService(nameOrdinal);
} catch (RemoteException e) {
Log.e(TAG, "getService: can't get service from cbb remote service");
return null;
}
switch (name) {
case CBB_CORE:
iInterface = ICbbCore.Stub.asInterface(binder);
break;
case ......//select binder by name
default:
iInterface = null;
break;
}
mCache.put(nameOrdinal, iInterface);
}
return iInterface;
}
}
その後、クライアントは getService によって返される IInterface を使用して RPC を実行できます。