2

次のように、グローバル バックグラウンド キューで の複数のインスタンスを同時に呼び出しているときに、アプリがデッドロック状態 (メイン スレッドが で待機中semaphore_wait_trap、以下のコール スタックを参照) で数回動かなくなっていることがわかります。CFStringTransform

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    CFStringTransform(…);
});

コール スタックは次のようになります。

Thread 1, Queue : com.apple.main-thread
#0  0x310bff04 in semaphore_wait_trap ()
#1  0x341c1fae in _dispatch_semaphore_wait_slow ()
#2  0x32bc5c32 in SBSProcessAssertionCreateForPID ()
#3  0x3685bca4 in -[UIApplication beginBackgroundTaskWithExpirationHandler:] ()
#4  0x0011a1c2 in -[XXX downloadPicture:]
…
#10 0x32f86a6e in __NSFireDelayedPerform ()
#11 0x354a15de in __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ ()
#12 0x354a1290 in __CFRunLoopDoTimer ()
#13 0x3549ff00 in __CFRunLoopRun ()
#14 0x35412ebc in CFRunLoopRunSpecific ()
#15 0x35412d48 in CFRunLoopRunInMode ()
#16 0x3594f2ea in GSEventRunModal ()
#17 0x367f1300 in UIApplicationMain ()
#18 0x000c3eb8 in main


Thread 3, Queue : com.apple.libdispatch-manager
#0  0x310c0648 in kevent64 ()
#1  0x341c3978 in _dispatch_mgr_invoke ()
#2  0x341c3658 in _dispatch_mgr_thread$VARIANT$mp ()


Thread 5 WebThread, Queue : (null)
#0  0x310bfeb4 in mach_msg_trap ()
#1  0x310c004c in mach_msg ()
#2  0x354a1044 in __CFRunLoopServiceMachPort ()
#3  0x3549fda2 in __CFRunLoopRun ()
#4  0x35412ebc in CFRunLoopRunSpecific ()
#5  0x35412d48 in CFRunLoopRunInMode ()
#6  0x349b6a74 in RunWebThread(void*) ()
#7  0x3925f310 in _pthread_start ()
#8  0x3925f1d8 in thread_start ()


Thread 11 com.apple.NSURLConnectionLoader, Queue : (null)
#0  0x310bfeb4 in mach_msg_trap ()
#1  0x310c004c in mach_msg ()
#2  0x354a1044 in __CFRunLoopServiceMachPort ()
#3  0x3549fda2 in __CFRunLoopRun ()
#4  0x35412ebc in CFRunLoopRunSpecific ()
#5  0x35412d48 in CFRunLoopRunInMode ()
#6  0x32f0bbcc in +[NSURLConnection(Loader) _resourceLoadLoop:] ()
#7  0x32f8f67c in __NSThread__main__ ()
#8  0x3925f310 in _pthread_start ()
#9  0x3925f1d8 in thread_start ()


Thread 14 com.apple.CFSocket.private, Queue : (null)
#0  0x310d0594 in select$DARWIN_EXTSN ()
#1  0x354a51f6 in __CFSocketManager ()
#2  0x3925f310 in _pthread_start ()
#3  0x3925f1d8 in thread_start ()

および 31 スレッドの呼び出しCFStringTransform:

Thread 12, Queue : com.apple.root.default-priority
#0  0x310d00fc in __psynch_mutexwait ()
#1  0x3924f128 in pthread_mutex_lock ()
#2  0x31448548 in umtx_lock ()
#3  0x3144a090 in icu::UnicodeString::doReplace(int, int, unsigned short const*, int, int) ()
#4  0x314a5b3a in icu::UnicodeString::append(int) ()
#5  0x314a1510 in icu::UnicodeSet::_appendToPat(icu::UnicodeString&, int, signed char) ()
#6  0x314a168c in icu::UnicodeSet::_generatePattern(icu::UnicodeString&, signed char) const ()
#7  0x314a2e4e in icu::UnicodeSet::applyPattern(icu::RuleCharacterIterator&, icu::SymbolTable const*, icu::UnicodeString&, unsigned int, icu::UnicodeSet& (icu::UnicodeSet::*)(int), UErrorCode&) ()
#8  0x314a1e7c in icu::UnicodeSet::applyPattern(icu::UnicodeString const&, icu::ParsePosition&, unsigned int, icu::SymbolTable const*, UErrorCode&) ()
#9  0x314a1e06 in icu::UnicodeSet::UnicodeSet(icu::UnicodeString const&, icu::ParsePosition&, unsigned int, icu::SymbolTable const*, UErrorCode&) ()
#10 0x314a1d8e in icu::UnicodeSet::UnicodeSet(icu::UnicodeString const&, icu::ParsePosition&, unsigned int, icu::SymbolTable const*, UErrorCode&) ()
#11 0x314fe56c in ___lldb_unnamed_function2011$$libicucore.A.dylib ()
#12 0x314fda50 in ___lldb_unnamed_function2010$$libicucore.A.dylib ()
#13 0x314fd954 in ___lldb_unnamed_function2009$$libicucore.A.dylib ()
#14 0x314ff540 in ___lldb_unnamed_function2031$$libicucore.A.dylib ()
#15 0x314feed6 in ___lldb_unnamed_function2025$$libicucore.A.dylib ()
#16 0x314feb0c in ___lldb_unnamed_function2024$$libicucore.A.dylib ()
#17 0x31521468 in ___lldb_unnamed_function2248$$libicucore.A.dylib ()
#18 0x3152015a in icu::Transliterator::createBasicInstance(icu::UnicodeString const&, icu::UnicodeString const*) ()
#19 0x31522cd6 in ___lldb_unnamed_function2296$$libicucore.A.dylib ()
#20 0x31523c32 in ___lldb_unnamed_function2305$$libicucore.A.dylib ()
#21 0x3152003a in icu::Transliterator::createInstance(icu::UnicodeString const&, UTransDirection, UParseError&, UErrorCode&) ()
#22 0x315200d6 in icu::Transliterator::createInstance(icu::UnicodeString const&, UTransDirection, UErrorCode&) ()
#23 0x314bfc1c in ___lldb_unnamed_function1051$$libicucore.A.dylib ()
#24 0x314bfb0e in ___lldb_unnamed_function1050$$libicucore.A.dylib ()
#25 0x3151fada in icu::Transliterator::filteredTransliterate(icu::Replaceable&, UTransPosition&, signed char, signed char) const ()
#26 0x3151f724 in icu::Transliterator::transliterate(icu::Replaceable&, int, int) const ()
#27 0x3154a8da in utrans_trans ()
#28 0x354b3928 in CFStringTransform ()
#30 0x002716c8 in __18-[Foo bar]_block_invoke_0
#31 0x341bd11e in _dispatch_call_block_and_release ()
#32 0x341c1960 in _dispatch_root_queue_drain ()
#33 0x341c1ac0 in _dispatch_worker_thread2 ()
#34 0x39254a10 in _pthread_wqthread ()
#35 0x392548a4 in start_wqthread ()

文字列変更呼び出しで問題が発生しているようdoReplaceです。ただし、doReplaceミューテックスを使用しているため、スレッドセーフであるようにも見えるため、複数のスレッドが同じ可変文字列を同時に変更しても問題ありません。実際、私の場合、変更可能な文字列が複数のスレッドによって変更されることはなく、それぞれCFStringTransformが一意の文字列に対して呼び出されます。基本的に、なぜそれが詰まっているのかわかりません。

4

1 に答える 1

0

面白い。

ICU 文字列変換は、 というライブラリに存在しますlibicucore。Mac OS 10.8 バージョンのソース コードは、こちらから入手できます

doReplace関数は に実装されていますが、直接icuSources/common/unistr.cpp呼び出すことはありません。umtx_lockiOS が別のバージョンのライブラリを使用するか、呼び出しがインライン関数 (またはプリプロセッサ マジック) 内にあるだけである可能性があります。そのため、ロックがグローバルに共有されているロックなのか、文字列ごとに 1 つあるのかを確認できませんでした。

とにかく、Mac OS (24k 文字列、10000 個のディスパッチされたブロック) でいくつかのテストを行いましたが、デッドロックを再現することに成功しませんでした。

コードがまだ実行されていませんか? すべてのスレッドが同じスタック フレームにあるか?

于 2012-10-05T18:34:24.877 に答える