Playdate Simulator occasionally hangs re-opening a game with mic access

There appears to be a dead-lock type of situation when the Playdate Simulator stops an audio graph from previously opened game. In practice this issue manifests itself in the Simulator UI being fully locked when either re-opening the game via menu, or when re-starting debugging session from VS Code.

It appears to be a platform-specific issue, as it happens for some people around on macOS, but does not happen on Linux.

System information:

  • MacBook Pro, Apple M3 Max
  • macOS 14.4.1 (23E224)
  • Playdate Simulator Version 2.4.2 (166897)

Repro steps:

  • Compile game with the code from below
  • Start simulator
  • Open the game in the simulator
  • Keep spamming File -> Open Recent -> <game.pdx>
  • Eventually the UI will stop responding

Example :

local gfx = playdate.graphics

function setup()
  playdate.sound.micinput.startListening()
end

setup()

gfx.setColor(gfx.kColorBlack)
gfx.fillRect(0, 0, 400, 240)
gfx.setBackgroundColor(gfx.kColorBlack)

gfx.setColor(gfx.kColorWhite)

function playdate.update()
  local volume = playdate.sound.micinput.getLevel()
end

Full back-trace after the simulator has hang up:

Process 10072 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
    frame #0: 0x0000000192d10ea4 libsystem_kernel.dylib`__psynch_mutexwait + 8
libsystem_kernel.dylib`:
->  0x192d10ea4 <+8>:  b.lo   0x192d10ec4               ; <+40>
    0x192d10ea8 <+12>: pacibsp
    0x192d10eac <+16>: stp    x29, x30, [sp, #-0x10]!
    0x192d10eb0 <+20>: mov    x29, sp
Target 0: (Playdate Simulator) stopped.
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
  * frame #0: 0x0000000192d10ea4 libsystem_kernel.dylib`__psynch_mutexwait + 8
    frame #1: 0x0000000192d4c060 libsystem_pthread.dylib`_pthread_mutex_firstfit_lock_wait + 84
    frame #2: 0x0000000192d499f0 libsystem_pthread.dylib`_pthread_mutex_firstfit_lock_slow + 248
    frame #3: 0x0000000195964eb0 CoreAudio`HALB_Mutex::Lock() + 128
    frame #4: 0x00000001955bfeb8 CoreAudio`HALC_ProxyIOContext::StopIOProc(int (*)(unsigned int, AudioTimeStamp const*, AudioBufferList const*, AudioTimeStamp const*, AudioBufferList*, AudioTimeStamp const*, void*)) + 48
    frame #5: 0x0000000195581878 CoreAudio`HAL_HardwarePlugIn_DeviceStop(AudioHardwarePlugInInterface**, unsigned int, int (*)(unsigned int, AudioTimeStamp const*, AudioBufferList const*, AudioTimeStamp const*, AudioBufferList*, AudioTimeStamp const*, void*)) + 1120
    frame #6: 0x0000000195644340 CoreAudio`AudioDeviceStop_mac_imp + 240
    frame #7: 0x00000001193cc050 CoreAudio`___lldb_unnamed_symbol972 + 72
    frame #8: 0x00000001193cbfc4 CoreAudio`___lldb_unnamed_symbol971 + 188
    frame #9: 0x00000001194cd6e0 CoreAudio`___lldb_unnamed_symbol4824 + 120
    frame #10: 0x0000000195111a80 AudioToolboxCore`AudioOutputUnitStop + 316
    frame #11: 0x00000001ecf81060 AVFAudio`AUInterfaceIOV3::StopIO() + 60
    frame #12: 0x00000001ed025eb8 AVFAudio`AVAudioEngineGraph::_Stop(NSError**) + 228
    frame #13: 0x00000001ed025d98 AVFAudio`AVAudioEngineGraph::Stop(NSError**) + 64
    frame #14: 0x00000001ed050df4 AVFAudio`AVAudioEngineImpl::Pause(NSError**) + 220
    frame #15: 0x00000001ed04e278 AVFAudio`AVAudioEngineImpl::Stop(NSError**) + 216
    frame #16: 0x00000001ed052274 AVFAudio`-[AVAudioEngine stop] + 48
    frame #17: 0x00000001000e53b8 Playdate Simulator`-[PCGameView stopAudio] + 32
    frame #18: 0x00000001000dec4c Playdate Simulator`-[PCPlaydateSimulator loadGame:] + 240
    frame #19: 0x00000001000d8710 Playdate Simulator`-[PCGamePreviewWindowController runGame:] + 112
    frame #20: 0x00000001000d0bd0 Playdate Simulator`-[AppDelegate application:openFile:] + 116
    frame #21: 0x0000000196ac2ef0 AppKit`-[NSApplication _doOpenFile:ok:tryTemp:] + 324
    frame #22: 0x0000000196ad4b50 AppKit`__88-[NSApplication(NSAppleEventHandling) _openURLs:requestedBySourceApp:completionHandler:]_block_invoke.41 + 292
    frame #23: 0x0000000196ad4434 AppKit`-[NSApplication(NSAppleEventHandling) _openURLs:requestedBySourceApp:completionHandler:] + 1108
    frame #24: 0x0000000196c16c7c AppKit`__55-[NSDocumentController(NSPrivate) _openRecentDocument:]_block_invoke + 240
    frame #25: 0x0000000196ae28b8 AppKit`-[_NSRecentItemsMenuController _handleOpenRecentItem:completionHandler:] + 120
    frame #26: 0x0000000196c16b20 AppKit`-[NSDocumentController(NSPrivate) _openRecentDocument:] + 228
    frame #27: 0x0000000196829c70 AppKit`-[NSApplication(NSResponder) sendAction:to:from:] + 460
    frame #28: 0x00000001968f34a4 AppKit`-[NSMenuItem _corePerformAction] + 372
    frame #29: 0x0000000196ea0af4 AppKit`_NSMenuPerformActionWithHighlighting + 152
    frame #30: 0x000000019692bbcc AppKit`-[NSMenu performActionForItemAtIndex:] + 200
    frame #31: 0x000000019692baec AppKit`-[NSMenu _internalPerformActionForItemAtIndex:] + 76
    frame #32: 0x0000000196e978d8 AppKit`+[NSCocoaMenuImpl _performActionForMenuItem:] + 84
    frame #33: 0x0000000196cc0a24 AppKit`-[NSMenuTrackingSession _performPostTrackingDismissalActions] + 276
    frame #34: 0x0000000196cc0790 AppKit`-[NSMenuTrackingSession startRunningMenuEventLoop:] + 1128
    frame #35: 0x0000000196d67574 AppKit`-[NSMenuBarTrackingSession _mouseDownEventHandler:] + 264
    frame #36: 0x0000000196d67454 AppKit`-[NSMenuBarTrackingSession handleEvent:] + 248
    frame #37: 0x0000000196d67334 AppKit`__57-[NSMenuBarTrackingSession _addLocalEventMonitorIfNeeded]_block_invoke + 192
    frame #38: 0x000000019687f6f8 AppKit`_NSSendEventToDequeuingObservers + 252
    frame #39: 0x0000000196e773c0 AppKit`-[NSApplication(NSEventRouting) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 2192
    frame #40: 0x0000000196677cb8 AppKit`-[NSApplication run] + 476
    frame #41: 0x000000019664ef54 AppKit`NSApplicationMain + 880
    frame #42: 0x00000001929c60e0 dyld`start + 2360
(lldb) bt all
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
  * frame #0: 0x0000000192d10ea4 libsystem_kernel.dylib`__psynch_mutexwait + 8
    frame #1: 0x0000000192d4c060 libsystem_pthread.dylib`_pthread_mutex_firstfit_lock_wait + 84
    frame #2: 0x0000000192d499f0 libsystem_pthread.dylib`_pthread_mutex_firstfit_lock_slow + 248
    frame #3: 0x0000000195964eb0 CoreAudio`HALB_Mutex::Lock() + 128
    frame #4: 0x00000001955bfeb8 CoreAudio`HALC_ProxyIOContext::StopIOProc(int (*)(unsigned int, AudioTimeStamp const*, AudioBufferList const*, AudioTimeStamp const*, AudioBufferList*, AudioTimeStamp const*, void*)) + 48
    frame #5: 0x0000000195581878 CoreAudio`HAL_HardwarePlugIn_DeviceStop(AudioHardwarePlugInInterface**, unsigned int, int (*)(unsigned int, AudioTimeStamp const*, AudioBufferList const*, AudioTimeStamp const*, AudioBufferList*, AudioTimeStamp const*, void*)) + 1120
    frame #6: 0x0000000195644340 CoreAudio`AudioDeviceStop_mac_imp + 240
    frame #7: 0x00000001193cc050 CoreAudio`___lldb_unnamed_symbol972 + 72
    frame #8: 0x00000001193cbfc4 CoreAudio`___lldb_unnamed_symbol971 + 188
    frame #9: 0x00000001194cd6e0 CoreAudio`___lldb_unnamed_symbol4824 + 120
    frame #10: 0x0000000195111a80 AudioToolboxCore`AudioOutputUnitStop + 316
    frame #11: 0x00000001ecf81060 AVFAudio`AUInterfaceIOV3::StopIO() + 60
    frame #12: 0x00000001ed025eb8 AVFAudio`AVAudioEngineGraph::_Stop(NSError**) + 228
    frame #13: 0x00000001ed025d98 AVFAudio`AVAudioEngineGraph::Stop(NSError**) + 64
    frame #14: 0x00000001ed050df4 AVFAudio`AVAudioEngineImpl::Pause(NSError**) + 220
    frame #15: 0x00000001ed04e278 AVFAudio`AVAudioEngineImpl::Stop(NSError**) + 216
    frame #16: 0x00000001ed052274 AVFAudio`-[AVAudioEngine stop] + 48
    frame #17: 0x00000001000e53b8 Playdate Simulator`-[PCGameView stopAudio] + 32
    frame #18: 0x00000001000dec4c Playdate Simulator`-[PCPlaydateSimulator loadGame:] + 240
    frame #19: 0x00000001000d8710 Playdate Simulator`-[PCGamePreviewWindowController runGame:] + 112
    frame #20: 0x00000001000d0bd0 Playdate Simulator`-[AppDelegate application:openFile:] + 116
    frame #21: 0x0000000196ac2ef0 AppKit`-[NSApplication _doOpenFile:ok:tryTemp:] + 324
    frame #22: 0x0000000196ad4b50 AppKit`__88-[NSApplication(NSAppleEventHandling) _openURLs:requestedBySourceApp:completionHandler:]_block_invoke.41 + 292
    frame #23: 0x0000000196ad4434 AppKit`-[NSApplication(NSAppleEventHandling) _openURLs:requestedBySourceApp:completionHandler:] + 1108
    frame #24: 0x0000000196c16c7c AppKit`__55-[NSDocumentController(NSPrivate) _openRecentDocument:]_block_invoke + 240
    frame #25: 0x0000000196ae28b8 AppKit`-[_NSRecentItemsMenuController _handleOpenRecentItem:completionHandler:] + 120
    frame #26: 0x0000000196c16b20 AppKit`-[NSDocumentController(NSPrivate) _openRecentDocument:] + 228
    frame #27: 0x0000000196829c70 AppKit`-[NSApplication(NSResponder) sendAction:to:from:] + 460
    frame #28: 0x00000001968f34a4 AppKit`-[NSMenuItem _corePerformAction] + 372
    frame #29: 0x0000000196ea0af4 AppKit`_NSMenuPerformActionWithHighlighting + 152
    frame #30: 0x000000019692bbcc AppKit`-[NSMenu performActionForItemAtIndex:] + 200
    frame #31: 0x000000019692baec AppKit`-[NSMenu _internalPerformActionForItemAtIndex:] + 76
    frame #32: 0x0000000196e978d8 AppKit`+[NSCocoaMenuImpl _performActionForMenuItem:] + 84
    frame #33: 0x0000000196cc0a24 AppKit`-[NSMenuTrackingSession _performPostTrackingDismissalActions] + 276
    frame #34: 0x0000000196cc0790 AppKit`-[NSMenuTrackingSession startRunningMenuEventLoop:] + 1128
    frame #35: 0x0000000196d67574 AppKit`-[NSMenuBarTrackingSession _mouseDownEventHandler:] + 264
    frame #36: 0x0000000196d67454 AppKit`-[NSMenuBarTrackingSession handleEvent:] + 248
    frame #37: 0x0000000196d67334 AppKit`__57-[NSMenuBarTrackingSession _addLocalEventMonitorIfNeeded]_block_invoke + 192
    frame #38: 0x000000019687f6f8 AppKit`_NSSendEventToDequeuingObservers + 252
    frame #39: 0x0000000196e773c0 AppKit`-[NSApplication(NSEventRouting) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 2192
    frame #40: 0x0000000196677cb8 AppKit`-[NSApplication run] + 476
    frame #41: 0x000000019664ef54 AppKit`NSApplicationMain + 880
    frame #42: 0x00000001929c60e0 dyld`start + 2360
  thread #2, queue = 'com.apple.root.default-qos'
    frame #0: 0x0000000192d14340 libsystem_kernel.dylib`kevent + 8
    frame #1: 0x000000010002b004 Playdate Simulator`__36-[PDDeviceConnection watchForDevice]_block_invoke + 540
    frame #2: 0x0000000192b9c750 libdispatch.dylib`_dispatch_call_block_and_release + 32
    frame #3: 0x0000000192b9e3e8 libdispatch.dylib`_dispatch_client_callout + 20
    frame #4: 0x0000000192ba1580 libdispatch.dylib`_dispatch_queue_override_invoke + 928
    frame #5: 0x0000000192bafea8 libdispatch.dylib`_dispatch_root_queue_drain + 392
    frame #6: 0x0000000192bb06b8 libdispatch.dylib`_dispatch_worker_thread2 + 156
    frame #7: 0x0000000192d4afd0 libsystem_pthread.dylib`_pthread_wqthread + 228
  thread #8
    frame #0: 0x0000000192d0fea4 libsystem_kernel.dylib`__workq_kernreturn + 8
  thread #11, name = 'com.apple.NSEventThread'
    frame #0: 0x0000000192d0e1f4 libsystem_kernel.dylib`mach_msg2_trap + 8
    frame #1: 0x0000000192d20b24 libsystem_kernel.dylib`mach_msg2_internal + 80
    frame #2: 0x0000000192d16e34 libsystem_kernel.dylib`mach_msg_overwrite + 476
    frame #3: 0x0000000192d0e578 libsystem_kernel.dylib`mach_msg + 24
    frame #4: 0x0000000192e2e058 CoreFoundation`__CFRunLoopServiceMachPort + 160
    frame #5: 0x0000000192e2c91c CoreFoundation`__CFRunLoopRun + 1208
    frame #6: 0x0000000192e2be0c CoreFoundation`CFRunLoopRunSpecific + 608
    frame #7: 0x00000001967adcb4 AppKit`_NSEventThread + 144
    frame #8: 0x0000000192d4ef94 libsystem_pthread.dylib`_pthread_start + 136
  thread #12
    frame #0: 0x0000000192d0fea4 libsystem_kernel.dylib`__workq_kernreturn + 8
  thread #13
    frame #0: 0x0000000192d0fea4 libsystem_kernel.dylib`__workq_kernreturn + 8
  thread #14, name = 'caulk.messenger.shared:17'
    frame #0: 0x0000000192d0e170 libsystem_kernel.dylib`semaphore_wait_trap + 8
    frame #1: 0x000000019d2bf624 caulk`caulk::semaphore::timed_wait(double) + 212
    frame #2: 0x000000019d2bf4d8 caulk`caulk::concurrent::details::worker_thread::run() + 36
    frame #3: 0x000000019d2bf1d8 caulk`void* caulk::thread_proxy<std::__1::tuple<caulk::thread::attributes, void (caulk::concurrent::details::worker_thread::*)(), std::__1::tuple<caulk::concurrent::details::worker_thread*>>>(void*) + 96
    frame #4: 0x0000000192d4ef94 libsystem_pthread.dylib`_pthread_start + 136
  thread #15, name = 'caulk.messenger.shared:high'
    frame #0: 0x0000000192d0e170 libsystem_kernel.dylib`semaphore_wait_trap + 8
    frame #1: 0x000000019d2bf624 caulk`caulk::semaphore::timed_wait(double) + 212
    frame #2: 0x000000019d2bf4d8 caulk`caulk::concurrent::details::worker_thread::run() + 36
    frame #3: 0x000000019d2bf1d8 caulk`void* caulk::thread_proxy<std::__1::tuple<caulk::thread::attributes, void (caulk::concurrent::details::worker_thread::*)(), std::__1::tuple<caulk::concurrent::details::worker_thread*>>>(void*) + 96
    frame #4: 0x0000000192d4ef94 libsystem_pthread.dylib`_pthread_start + 136
  thread #16, name = 'caulk::deferred_logger'
    frame #0: 0x0000000192d0e170 libsystem_kernel.dylib`semaphore_wait_trap + 8
    frame #1: 0x000000019d2bf624 caulk`caulk::semaphore::timed_wait(double) + 212
    frame #2: 0x000000019d2bf4d8 caulk`caulk::concurrent::details::worker_thread::run() + 36
    frame #3: 0x000000019d2bf1d8 caulk`void* caulk::thread_proxy<std::__1::tuple<caulk::thread::attributes, void (caulk::concurrent::details::worker_thread::*)(), std::__1::tuple<caulk::concurrent::details::worker_thread*>>>(void*) + 96
    frame #4: 0x0000000192d4ef94 libsystem_pthread.dylib`_pthread_start + 136
  thread #17, name = 'com.apple.audio.toolbox.AUScheduledParameterRefresher'
    frame #0: 0x0000000192d0e170 libsystem_kernel.dylib`semaphore_wait_trap + 8
    frame #1: 0x000000019d2bf624 caulk`caulk::semaphore::timed_wait(double) + 212
    frame #2: 0x000000019d2bf4d8 caulk`caulk::concurrent::details::worker_thread::run() + 36
    frame #3: 0x000000019d2bf1d8 caulk`void* caulk::thread_proxy<std::__1::tuple<caulk::thread::attributes, void (caulk::concurrent::details::worker_thread::*)(), std::__1::tuple<caulk::concurrent::details::worker_thread*>>>(void*) + 96
    frame #4: 0x0000000192d4ef94 libsystem_pthread.dylib`_pthread_start + 136
  thread #19, name = 'com.apple.NSURLConnectionLoader'
    frame #0: 0x0000000192d0e1f4 libsystem_kernel.dylib`mach_msg2_trap + 8
    frame #1: 0x0000000192d20b24 libsystem_kernel.dylib`mach_msg2_internal + 80
    frame #2: 0x0000000192d16e34 libsystem_kernel.dylib`mach_msg_overwrite + 476
    frame #3: 0x0000000192d0e578 libsystem_kernel.dylib`mach_msg + 24
    frame #4: 0x0000000192e2e058 CoreFoundation`__CFRunLoopServiceMachPort + 160
    frame #5: 0x0000000192e2c91c CoreFoundation`__CFRunLoopRun + 1208
    frame #6: 0x0000000192e2be0c CoreFoundation`CFRunLoopRunSpecific + 608
    frame #7: 0x00000001982c5890 CFNetwork`___lldb_unnamed_symbol14489 + 384
    frame #8: 0x0000000193f58520 Foundation`__NSThread__start__ + 716
    frame #9: 0x0000000192d4ef94 libsystem_pthread.dylib`_pthread_start + 136
  thread #20
    frame #0: 0x0000000192d0fea4 libsystem_kernel.dylib`__workq_kernreturn + 8
  thread #21
    frame #0: 0x0000000192d0fea4 libsystem_kernel.dylib`__workq_kernreturn + 8
  thread #22
    frame #0: 0x0000000192d0fea4 libsystem_kernel.dylib`__workq_kernreturn + 8
  thread #23
    frame #0: 0x0000000192d0fea4 libsystem_kernel.dylib`__workq_kernreturn + 8
  thread #24
    frame #0: 0x0000000192d0fea4 libsystem_kernel.dylib`__workq_kernreturn + 8
  thread #25
    frame #0: 0x0000000192d0fea4 libsystem_kernel.dylib`__workq_kernreturn + 8
  thread #26
    frame #0: 0x0000000000000000
  thread #27, name = 'com.apple.audio.IOThread.client'
    frame #0: 0x0000000192d10ea4 libsystem_kernel.dylib`__psynch_mutexwait + 8
    frame #1: 0x0000000192d4c060 libsystem_pthread.dylib`_pthread_mutex_firstfit_lock_wait + 84
    frame #2: 0x0000000192d499f0 libsystem_pthread.dylib`_pthread_mutex_firstfit_lock_slow + 248
    frame #3: 0x0000000192c7a8a8 libc++.1.dylib`std::__1::recursive_mutex::lock() + 16
    frame #4: 0x00000001ed03883c AVFAudio`-[AVAudioNode inputFormatForBus:] + 52
    frame #5: 0x00000001000e4ca4 Playdate Simulator`__51-[PCGameView _startAudioRecordingCallback:context:]_block_invoke + 68
    frame #6: 0x00000001ecfa56dc AVFAudio`invocation function for block in AUGraphSinkNodeV3::AllocateRenderBlock() + 112
    frame #7: 0x00000001ed023ec8 AVFAudio`AVAudioEngineGraph::InputAvailable(void*, unsigned int*, AudioTimeStamp const*, unsigned int, unsigned int, AudioBufferList*) + 696
    frame #8: 0x000000019507bbf4 AudioToolboxCore`AUHALOutputUnit_InputAvailableCallback(void*, unsigned int*, AudioTimeStamp const*, unsigned int, unsigned int, AudioBufferList*) + 40
    frame #9: 0x00000001193ce5b0 CoreAudio`___lldb_unnamed_symbol1017 + 2120
    frame #10: 0x00000001955bcfb8 CoreAudio`HALC_ProxyIOContext::IOWorkLoop() + 9508
    frame #11: 0x00000001955ba35c CoreAudio`invocation function for block in HALC_ProxyIOContext::HALC_ProxyIOContext(unsigned int, unsigned int) + 108
    frame #12: 0x00000001957404e4 CoreAudio`HALC_IOThread::Entry(void*) + 88
    frame #13: 0x0000000192d4ef94 libsystem_pthread.dylib`_pthread_start + 136
(lldb)```
1 Like

Thanks, I was able to reproduce this and will have it fixed in a future release. Thanks again!