2012-10-05 41 views
2

我看到我的應用程序是停留在僵局狀態(主線程等待semaphore_wait_trap,請參見下面的調用堆棧)數次,而在全球背景隊列同時調用的CFStringTransform不止一個實例如下: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被稱爲唯一字符串。所以基本上,我不知道它爲什麼卡住了。

回答

0

有趣。

ICU字符串轉換存在於名爲libicucore的庫中。 Mac OS 10.8版本的源代碼is available here

doReplace函數在icuSources/common/unistr.cpp中實現,但它不直接調用umtx_lock。 iOS可能會使用其他版本的庫,或者這個調用可能只是在內聯函數(或預處理器魔術)內部。所以我找不到鎖是全局共享鎖還是每個字符串都有一個鎖。

無論如何,我在Mac OS上做了一些測試(24k字符串,10000個調度塊),但沒有成功重現死鎖。

你確定你的代碼還沒有運行嗎?所有線程都在同一個堆棧框架中嗎?

+0

是的,它被卡住了,調用'doReplace'的所有線程都有相同的堆棧跟蹤。正如你發現iOS和OS X不同,也許你應該在iOS上測試? – an0