Я вижу, что мое приложение застряло в состоянии тупикового (основной поток ожидает в 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
вызывается для уникальной строки. Так что, в основном, я не знаю, почему он застрял.
Да, он застрял, и все потоки, вызывающие 'doReplace', имеют одну и ту же трассировку стека. Как вы обнаружили, что iOS и OS X разные, может быть, вам следует протестировать iOS? – an0