MusicPlayerSetPlayRateScalar 在 __psynch_mutexwait 中导致 hang/freeze
MusicPlayerSetPlayRateScalar causes hang/freeze in __psynch_mutexwait
我正在使用 AVFoundation
的 MusicPlayer
在游戏中播放 MIDI 音乐,我会定期调用 MusicPlayerSetPlayRateScalar
来设置速度。我最近将游戏从 Objective-C 移植到 Swift,从那时起,在调用此函数几十次后,我一直在 hanging/freezing。当冻结发生并且我暂停执行时,我的主线程始终处于以下状态:
* thread #1: libsystem_kernel.dylib`__psynch_mutexwait + 8, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
* frame #0: libsystem_kernel.dylib`__psynch_mutexwait + 8
frame #1: libsystem_pthread.dylib`_pthread_mutex_lock_wait + 96
frame #2: AudioToolbox`CAMutex::Lock() + 52
frame #3: AudioToolbox`SequencePlayer::SetTempoScaleFactor(double) + 36
frame #4: AudioToolbox`MusicPlayerSetPlayRateScalar + 136
CPU 发生这种情况时,使用率会跃升至 100%,并且内存使用率开始稳步增长。我没有自己的任何其他线程 运行。另一个线程 activity 有所不同,但这是一个示例(其他线程堆栈跟踪的顶层):
thread #5: libsystem_kernel.dylib`kevent_qos + 8, queue = 'com.apple.libdispatch-manager'
thread #6: libsystem_kernel.dylib`__semwait_signal + 8, name = 'gputools.smt_poll.0x126fe8680'
thread #10: libsystem_kernel.dylib`mach_msg_trap + 8, name = 'com.apple.coreaudio.AQClient'
thread #11: libsystem_kernel.dylib`semaphore_wait_trap + 8, name = 'AudioStreamerImpl::sIOWorkerProcess'
thread #12: libc++abi.dylib`__cxa_decrement_exception_refcount + 32, name = 'AURemoteIO::IOThread'
thread #13: libsystem_kernel.dylib`mach_msg_trap + 8, name = 'AURemoteIO::IOThread'
鉴于互斥锁和信号量,我猜到某种死锁,但 CPU 和内存使用模式似乎表明情况并非如此。我该如何进一步调试?
(顺便说一句,当我在这种情况下执行 bt all
时,调试器有时会崩溃,但我怀疑这是否相关。)
Apple 人员在 WWDC 2015 Core Audio 视频中所说的话让我觉得在像这样的领域幕后有很多 C++ 巫术,因此 Swift 无法接口除非你采取某些预防措施(我不明白它们是什么)。在这种情况下,如果您不需要向后兼容性太远,您可能想尝试使用新的 AVAudioSequencer。我发现它非常简单可靠。
我正在使用 AVFoundation
的 MusicPlayer
在游戏中播放 MIDI 音乐,我会定期调用 MusicPlayerSetPlayRateScalar
来设置速度。我最近将游戏从 Objective-C 移植到 Swift,从那时起,在调用此函数几十次后,我一直在 hanging/freezing。当冻结发生并且我暂停执行时,我的主线程始终处于以下状态:
* thread #1: libsystem_kernel.dylib`__psynch_mutexwait + 8, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
* frame #0: libsystem_kernel.dylib`__psynch_mutexwait + 8
frame #1: libsystem_pthread.dylib`_pthread_mutex_lock_wait + 96
frame #2: AudioToolbox`CAMutex::Lock() + 52
frame #3: AudioToolbox`SequencePlayer::SetTempoScaleFactor(double) + 36
frame #4: AudioToolbox`MusicPlayerSetPlayRateScalar + 136
CPU 发生这种情况时,使用率会跃升至 100%,并且内存使用率开始稳步增长。我没有自己的任何其他线程 运行。另一个线程 activity 有所不同,但这是一个示例(其他线程堆栈跟踪的顶层):
thread #5: libsystem_kernel.dylib`kevent_qos + 8, queue = 'com.apple.libdispatch-manager'
thread #6: libsystem_kernel.dylib`__semwait_signal + 8, name = 'gputools.smt_poll.0x126fe8680'
thread #10: libsystem_kernel.dylib`mach_msg_trap + 8, name = 'com.apple.coreaudio.AQClient'
thread #11: libsystem_kernel.dylib`semaphore_wait_trap + 8, name = 'AudioStreamerImpl::sIOWorkerProcess'
thread #12: libc++abi.dylib`__cxa_decrement_exception_refcount + 32, name = 'AURemoteIO::IOThread'
thread #13: libsystem_kernel.dylib`mach_msg_trap + 8, name = 'AURemoteIO::IOThread'
鉴于互斥锁和信号量,我猜到某种死锁,但 CPU 和内存使用模式似乎表明情况并非如此。我该如何进一步调试?
(顺便说一句,当我在这种情况下执行 bt all
时,调试器有时会崩溃,但我怀疑这是否相关。)
Apple 人员在 WWDC 2015 Core Audio 视频中所说的话让我觉得在像这样的领域幕后有很多 C++ 巫术,因此 Swift 无法接口除非你采取某些预防措施(我不明白它们是什么)。在这种情况下,如果您不需要向后兼容性太远,您可能想尝试使用新的 AVAudioSequencer。我发现它非常简单可靠。