Как я могу отладить этот тупик при выпуске AVAudioPlayer?

В моем приложении для iPhone у меня есть экземпляр AVAudioPlayer, который я выпускаю (чтобы затем я мог инициализировать другой экземпляр с другим URL-адресом вместо него). Обычно это работает нормально, но иногда я получаю тупик в основном потоке:

Thread 1, Queue : com.apple.main-thread
#0  0x357e00d8 in __psynch_mutexwait ()
#1  0x3497d67a in pthread_mutex_lock ()
#2  0x359997a6 in -[AVAudioPlayer privCommonCleanup] ()
#3  0x35999bb6 in -[AVAudioPlayer dealloc] ()
#4  0x3338a174 in _objc_rootRelease ()

Приложение просто зависает, не принимая никаких данных. Никаких сбоев или чего-то еще, он просто останавливается.

Похоже, что он не взаимодействует ни с одним из других потоков в приложении, но для полноты картины они здесь:

Thread 2, Queue : com.apple.libdispatch-manager
#0  0x357d03a8 in kevent ()
#1  0x33b03eaa in _dispatch_mgr_invoke ()
#2  0x33b03bc8 in _dispatch_mgr_thread ()
Thread 3, Queue : (null)
#0  0x357e0cd4 in __workq_kernreturn ()
#1  0x34983f3c in _pthread_wqthread ()
#2  0x34983cd0 in start_wqthread ()
Thread 4 WebThread, Queue : (null)
#0  0x357d0004 in mach_msg_trap ()
#1  0x357d0200 in mach_msg ()
#2  0x3573e3f2 in __CFRunLoopServiceMachPort ()
#3  0x3573d12a in __CFRunLoopRun ()
#4  0x356c04a4 in CFRunLoopRunSpecific ()
#5  0x356c036c in CFRunLoopRunInMode ()
#6  0x37406ca2 in _ZL12RunWebThreadPv ()
#7  0x34989734 in _pthread_start ()
#8  0x349895f0 in thread_start ()
Thread 5, Queue : (null)
#0  0x357e0cd4 in __workq_kernreturn ()
#1  0x34983f3c in _pthread_wqthread ()
#2  0x34983cd0 in start_wqthread ()
Thread 6 AQClient, Queue : (null)
#0  0x357d0004 in mach_msg_trap ()
#1  0x357d0200 in mach_msg ()
#2  0x3573e3f2 in __CFRunLoopServiceMachPort ()
#3  0x3573d12a in __CFRunLoopRun ()
#4  0x356c04a4 in CFRunLoopRunSpecific ()
#5  0x356c036c in CFRunLoopRunInMode ()
#6  0x34e2cb2e in GenericRunLoopThread::Entry(void*) ()
#7  0x34db3ca2 in CAPThread::Entry(CAPThread*) ()
#8  0x34989734 in _pthread_start ()
#9  0x349895f0 in thread_start ()
Thread 7, Queue : (null)
#0  0x357d0004 in mach_msg_trap ()
#1  0x357d0200 in mach_msg ()
#2  0x3573e3f2 in __CFRunLoopServiceMachPort ()
#3  0x3573d12a in __CFRunLoopRun ()
#4  0x356c04a4 in CFRunLoopRunSpecific ()
#5  0x356c036c in CFRunLoopRunInMode ()
#6  0x34af9b74 in -[NSRunLoop(NSRunLoop) runMode:beforeDate:] ()
#7  0x34b13522 in -[NSRunLoop(NSRunLoop) run] ()
#8  0x000c83fe in +[AFURLConnectionOperation networkRequestThreadEntryPoint:] at /Users/hiltonc/Documents/Code/LDSMobileApps/LDSScriptureHeroes/External/LDSMobileAccount/External/AFNetworking/AFNetworking/AFURLConnectionOperation.m:151
#9  0x34b05a80 in -[NSThread main] ()
Thread 8 com.apple.NSURLConnectionLoader, Queue : (null)
#0  0x357d0004 in mach_msg_trap ()
#1  0x357d0200 in mach_msg ()
#2  0x3573e3f2 in __CFRunLoopServiceMachPort ()
#3  0x3573d12a in __CFRunLoopRun ()
#4  0x356c04a4 in CFRunLoopRunSpecific ()
#5  0x356c036c in CFRunLoopRunInMode ()
#6  0x34b05bb8 in +[NSURLConnection(Loader) _resourceLoadLoop:] ()
#7  0x34b05a80 in -[NSThread main] ()
Thread 12 com.apple.CFSocket.private, Queue : (null)
#0  0x357e0570 in select$DARWIN_EXTSN ()
#1  0x35742640 in __CFSocketManager ()
#2  0x34989734 in _pthread_start ()
#3  0x349895f0 in thread_start ()

Я действительно понятия не имею, как добраться до сути этой проблемы. Любые идеи?


person Hilton Campbell    schedule 17.07.2012    source источник
comment
ну, у вас есть последний вызванный метод. Почему бы вам не посмотреть места, где вы выпускаете свой AVAudioPlayer? Или, может быть, разместить его здесь, чтобы мы могли посмотреть? Одна вещь, на которую следует обратить внимание, — это методы dispatch_sync, которые делают ошибку. Я не думаю, что они вернутся должным образом, и это заблокирует ваше приложение.   -  person borrrden    schedule 17.07.2012
comment
Можете ли вы попытаться преобразовать несколько экземпляров avaudioplayer в один в делегате, тогда у него будет меньше шансов на сбой или взаимоблокировку, как этот ответ: - stackoverflow.com/questions/8467533/   -  person Dhaval Panchal    schedule 17.07.2012
comment
@Dhaval отличная идея, но у меня есть несколько десятков звуков, которые я играю, и я не могу найти способ изменить URL-адрес проигрывателя после его создания.   -  person Hilton Campbell    schedule 17.07.2012


Ответы (1)


Освобождение одного и замена его в вызове делегата наверняка вызовет проблему такого типа. По сути, вы хотите запустить (под ARC):

avPlayer.delegate = nil
[avPlayer stop];
avPlayer = nil; //overkill
avPlayer = [AVPlayer alloc] init....
avPlayer ....

Если вы обнаружите, что вам нужно сделать это в методе делегата, просто оберните приведенный выше код в блок и отправьте его в основную очередь (я предполагаю, что avPlayer является ivar или свойством).

person David H    schedule 17.07.2012
comment
У меня есть выпуск, происходящий при вызове делегата, но отправка в основную очередь не исправила это. Я вставил операторы журнала во все методы, связанные со звуком, включая обратные вызовы делегатов, но все они происходят в основном потоке. Установка делегата в nil перед вызовом остановки действительно решила проблему. Судя по всему, происходило двойное освобождение, которое проявлялось в виде тупиковой ситуации. Странный. Благодарю вас! - person Hilton Campbell; 17.07.2012
comment
На всякий случай я бы сделал приведенный выше блок кода в основном потоке, если вы можете. Если вы этого не сделаете, когда делегат вернется, объект может попытаться выполнить некоторый код, даже если он был выпущен. Хотя это может не вызвать у вас проблем сейчас, это может произойти в новом выпуске. Я укусил это большое время с объектом CLLocation, и он только разбился с iOS 4.3 на телефоне 3GS! - person David H; 17.07.2012
comment
Хорошая точка зрения. Да, я поставлю своего делегата в основной поток, чтобы быть уверенным. Спасибо еще раз! - person Hilton Campbell; 17.07.2012