2017-05-24 12 views
0

system_serverにデッドロックが発生しており、ロックはPackageManagerによって保持されています。GetStringCriticalのデッドロックが発生する可能性がありますか?

"PackageManager" prio=5 tid=27 WaitingForGcToComplete 
    | group="main" sCount=1 dsCount=0 obj=0x12d3e7b0 self=0xb865c1a0 
    | sysTid=579 nice=0 cgrp=default sched=0/0 handle=0xb865c788 
    | state=S schedstat=(82300981 68593861 146) utm=6 stm=2 core=1 HZ=100 
    | stack=0xa0fdb000-0xa0fdd000 stackSize=1036KB 
    | held mutexes= 
    native: #00 pc 00012960 /system/lib/libc.so (syscall+28) 
    native: #01 pc 000a88ad /system/lib/libart.so(art::Mutex::ExclusiveLock(art::Thread*)+364) 
    native: #02 pc 0013aa7b /system/lib/libart.so (art::gc::Heap::IncrementDisableMovingGC(art::Thread*)+90) 
    native: #03 pc 001c0329 /system/lib/libart.so (art::JNI::GetStringCritical(_JNIEnv*, _jstring*, unsigned char*)+392) 
    native: #04 pc 00082223 /system/lib/libandroid_runtime.so (???) 
    native: #05 pc 00082291 /system/lib/libandroid_runtime.so (???) 
    native: #06 pc 00263595 /data/dalvik-cache/arm/[email protected]@boot.oat (Java_android_os_Parcel_nativeWriteString__JLjava_lang_String_2+120) 
    at android.os.Parcel.nativeWriteString(Native method) 
    at android.os.Parcel.writeString(Parcel.java:542) 
    at android.content.ComponentName.writeToParcel(ComponentName.java:267) 
    at android.content.ComponentName.writeToParcel(ComponentName.java:282) 
    at android.content.Intent.writeToParcel(Intent.java:7486) 
    at android.app.ApplicationThreadProxy.scheduleUnbindService(ApplicationThreadNative.java:929) 
    at com.android.server.am.ActiveServices.removeConnectionLocked(ActiveServices.java:1842) 
    at com.android.server.am.ActiveServices.unbindServiceLocked(ActiveServices.java:943) 
    at com.android.server.am.ActivityManagerService.unbindService(ActivityManagerService.java:15787) 
    - locked <0x1d3e13e9> (a com.android.server.am.ActivityManagerService) 

だから私はそれをGoogleや他のいくつかのJNIは、GCがブロックされている場合、デッドロックが発生する可能性があり、GetStringCriticalとReleaseStringCriticalの間の通話があるかどうかを調べます。 詳細を参照するためThe Java Native Interface: Programmer's Guide and Specification

これはフレームワークのメソッドandroid_os_Parcel_writeString \ベース\コア\ JNI \ android_os_Parcel.cppの一部です。

const jchar* str = env->GetStringCritical(val, 0); 
    if (str) { 
     err = parcel->writeString16(str, env->GetStringLength(val)); 
     env->ReleaseStringCritical(val, str); 
    } 

私はandroid_os_Parcel_writeStringは非常に一般的に使用される方法であるため、デッドロックがandroid_os_Parcel_writeStringによって原因であることを確認することはできません。

ですから、android_os_Parcel_writeStringがデッドロックの原因になることがありますか?

あなたの答えに感謝し、私の厄介な英語を忘れてください。

答えて

0

GetStringCriticalは、細心の注意を払って使用する必要があります。 GetStringCriticalで取得したポインタを保持している間は、ネイティブコードがJVM内に新しいオブジェクトを割り当てたり、システムがデッドロックする可能性のある他のブロッキング呼び出しを実行したりしないようにしてください。

/* This is not safe! */ 
const char *c_str = (*env)->GetStringCritical(env, j_str, 0); 
if (c_str == NULL) { 
... /* error handling */ 
} 
fprintf(fd, "%s\n", c_str); 
(*env)->ReleaseStringCritical(env, j_str, c_str); 

コードの問題は、ガベージコレクションが現在のスレッドによって無効にされたときに、ファイル ハンドルに書き込むために、常に安全ではないということです。 の例では、別のthread Tfdファイルハンドルからの読み取りを待機しています。 はさらに、 fprintfコールが、がすべての保留中のデータをfdから読み終えるまで待機するように、オペレーティングシステムのバッファリングが設定されているものとします。 は、デッドロックの可能性のあるシナリオを構築しました。thread Tがファイルハンドルから読み取るバッファとして機能するのに十分なメモリを 割り当てることができない場合、 はガベージコレクションを要求する必要があります。現在のスレッドがReleaseStringCriticalを実行するまで までガベージコレクション要求がブロックされます。これは の呼び出しが返されるまで発生しません。 fprintfコールthread Thttps://android.googlesource.com/platform/frameworks/base/+/master/core/jni/android_os_Parcel.cppを見た後

を扱うファイルからの読み込みを終了するために、しかし、待っているが、この方法writeString16はデッドロックフリーです。これまでのところParcelに関する問題はありません。

関連する問題