Crash in mixerSuspend

We encountered an Android ARM64 crash inside the FMOD mixer thread while calling System::mixerSuspend(). The complete FMOD logging-library output is available and will be attached.

Environment:

  • FMOD Engine: 2.03.14
  • FMOD library: libfmodL.so, ARM64
  • Device: Samsung SM-A715F
  • OS: Android 12 / SDK 31
  • Application build: 26.5.0.42912
  • FMOD output: AAudio
  • Output configuration: default output, 48 kHz, stereo
  • Local libfmodL.so build ID: 7f6812d87ea9d1a9ea3369c789434094

Crash summary:

Thread: FMOD mixer thre
Signal: 11 (Segmentation fault)
Fault address: 0x0000000000000000

0 libc.so sem_post
1 libfmodL.so 0x140f90
2 libfmodL.so 0x140f90
3 libfmodL.so 0x1381a8
4 libfmodL.so 0x1409d8
5 libc.so
6 libc.so

The crash happened during:

DeviceManagerPollEvents
→ Pause
→ FMODAudioManager
→ FMOD_System_MixerSuspend

Relevant sequence from the log:

  1. FMOD successfully initialized with AAudio:

20:56:06.615
FMOD output after initialization:
type=AAudio (18), drivers=4, selected driver=0 ‘(Default Output)’,
rate=48000 Hz, speaker mode=3, channels=2

  1. The application completed two earlier mixer suspend/resume cycles successfully. Each cycle logged:

FMOD mixer suspend requested
SystemI::mixerSuspend: Suspending output.
Thread::callback: FMOD mixer thread finished.
FMOD mixer suspend completed

FMOD mixer resume requested
Thread::initThread: Init FMOD mixer thread.
FMOD mixer resume completed

  1. Microphone capture was subsequently opened:

20:56:54.272
MicrophoneController: Starting audio capture at 44100 Hz

20:56:54.548
AudioManager: Opened audio capture device with sample rate 44100,
frames 2048, channels 1.

  1. Approximately one minute later, while the application was active and not paused, FMOD failed to stop an AAudio stream:

20:57:53.727
fmod_output_aaudio.cpp:201 AAudio_StopStreamBlocking
Failed to stop stream after 1000ms. State = 13. Result = -885.

20:57:53.728
fmod_output_aaudio.cpp:1010 AAudio_Stop
Cannot stop stream. Result = 0xFFFFFC8B.

At this point the diagnostic context reported:

Paused:false
StackInfo:/Update/GameAudioManager

We understand state 13 to be AAUDIO_STREAM_STATE_DISCONNECTED and result -885 to be AAUDIO_ERROR_TIMEOUT.

  1. FMOD then automatically reconstructed the output:

20:57:54.202
AAudio_CreateOutputStream:
Could not set driver at index [0]. Defaulting to driver with id: 3.

20:57:54.202
AAudio_Init:
Sample rate: HW = 48000, SW = 24000
Block size: HW = 192, SW = 512.

20:57:54.207
Thread::initThread:
Init FMOD mixer thread. Semaphore: Yes, Looping: Yes.

20:57:54.209
Thread::callback:
FMOD mixer thread finished.

Before this reinitialization, the hardware block size was 96 rather than 192.

  1. About five seconds later, the application was paused because the user started an Android in-app purchase:

20:57:58.934
StartBuying(com.outfit7.xxx.soc_bundle)

20:57:58.954
Extern call: Pause

The application first closed its microphone capture device and then suspended FMOD:

20:57:58.968
MicrophoneController: Stopping audio capture

20:57:58.968
AudioManager: Closing audio capture device

20:57:59.043
FMOD pause callback: initialized=1, mixer suspended=0

20:57:59.044
FMOD mixer suspend requested: suspended before=0

20:57:59.044
SystemI::mixerSuspend:
Suspending output.

20:57:59.046
Thread::callback:
FMOD mixer thread finished.

20:57:59.055
CRASH: FMOD mixer thread, SIGSEGV, fault address 0x0

The FMOD mixer suspend completed message was never reached.

We inspected the bundled ARM64 binary around the crash offsets. The sequence corresponding to the stack is:

0x1381a0 Load a semaphore pointer from the FMOD thread object
0x1381a4 Call FMOD’s semaphore-post wrapper
0x140f8c Call libc sem_post
0x140f90 Return address reported in the crash
0x1381a8 Caller return address reported in the crash
0x1409d8 FMOD OS thread trampoline after the thread callback

This appears to indicate that the mixer thread logged that it had finished and then attempted to post a null or already-cleared internal completion semaphore.

Integration details:

  • mixerSuspend() and mixerResume() are called from the same main/lifecycle thread.
  • Duplicate suspend/resume requests are guarded.
  • FMOD Studio updates are skipped while the mixer is suspended.
  • During the fatal transition, an asynchronous UI sound load completed before the pause handler called mixerSuspend().
  • We do not see another project-initiated FMOD API call after the final mixerSuspend() begins.
  • Earlier suspend/resume cycles in the same session completed successfully.
  • The crash only occurred after the AAudio stop timeout and automatic output/mixer-thread reconstruction.

Thank you for the detailed write up. I can reproduce the Failed to stop stream error by disconnecting headphones during a suspend, but I haven’t reproduced a segfault yet.

If you have the full log available, can you please upload it to your FMOD Profile?

its up

any info on this?

Sorry for the delay, I’ve got a hypothetical reproduction of this issue- the problem is with a recent change that was supposed to solve a similar deadlock, but now means the mixer thread won’t close if an error is encountered during mixerSuspend, resulting in the mixer thread calling into a freed semaphore.
I’ll write this up for the dev team to fix in a future release, thank you for reporting this issue.
The only workaround for the time being would be to pause/unpause the master bus during background/foreground transitions instead of suspending/resuming the mixer. i.e

FMOD::Studio::Bus* masterBus;
system->getBus("bus:/", &masterBus);
FMOD::ChannelGroup* masterChannelGroup;
masterBus->getChannelGroup(&masterChannelGroup);

//Suspend
masterChannelGroup->setPaused(true);

//Reume
masterChannelGroup->setPaused(false);

ok, we’ll see how critical it is when we go live. any timeline on the fix?

We are close to the end of our current release window, so it has been scheduled for the release after that, likely in a month’s time.
I can however get you a non-QA approved build once the fix becomes available.

Yeah, that would be nice :slight_smile:

Thanks

If I read correctly, current android impl of mixerSuspend/Resume shuts down audio device?

Yes as of 2.03.06 mixerSuspend shuts down the audio device on Android. This was to prevent an audio glitch:

  • Core API - Android - Fixed small amount of old audio being played after calling System::mixerResume when using OpenSL or AAudio output types.

We are also having some issues on android with native os video recorders. On some samsung device we see long freezes when video recording is started, while on some pixel devices, recorder does not “collect” audio - the video is silent during playback. Need to try with mainbus pause/resume…