Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Crash due to audio session observer race condition #2900

Closed
SDLBugzilla opened this issue Feb 11, 2021 · 0 comments
Closed

Crash due to audio session observer race condition #2900

SDLBugzilla opened this issue Feb 11, 2021 · 0 comments

Comments

@SDLBugzilla
Copy link
Collaborator

This bug report was migrated from our old Bugzilla tracker.

Reported in version: 2.0.8
Reported for operating system, platform: macOS 10.13, iPhone/iPod touch

Comments on the original bug report:

On 2018-05-15 15:26:07 +0000, Jona wrote:

There is a race condition crash when trying to remove the audio session observer. Basically we are setting the listeners device to NULL inside a "@synchronized" call but right after the synchronized call we are removing the observer.

if (this->hidden->interruption_listener != NULL)
{
SDLInterruptionListener *listener = nil;
listener = (SDLInterruptionListener *) CFBridgingRelease(this->hidden->interruption_listener);
@synchronized (listener) {
listener.device = NULL;
}
[center removeObserver:listener];
}

This leads to the problem where the audioSessionInterruption is called and it no longer has a valid "self.device" value. This NULL value is not handled and passed directly to the "interruption_begin" method where things crash.

  • (void)audioSessionInterruption:(NSNotification *)note
    {
    @synchronized (self) {
    NSNumber *type = note.userInfo[AVAudioSessionInterruptionTypeKey];
    if (type.unsignedIntegerValue == AVAudioSessionInterruptionTypeBegan) {
    interruption_begin(self.device);
    } else {
    interruption_end(self.device);
    }
    }
    }

The solution could likely be to call "[center removeObserver:listener];" before setting the "listener.device" to NULL.

On 2018-05-21 03:02:21 +0000, Sam Lantinga wrote:

That sounds right to me. Can you provide a tested patch?

Thanks!

On 2018-05-22 14:14:19 +0000, Jona wrote:

After further exploration and allowing our app to be beta tested by various users we noticed that the fix mentioned here did not resolve the problem.

Further testing and experimentation we discovered the issue and a fix!

The following explains why this bug was happening:
This crash was caused because the audio session was being set as active [session setActive:YES error:&err] when the audio device was actually being CLOSED. Certain cases the audio session being set to active would fail and the method would return right away. Because of the way the error was handled we never removed the SDLInterruptionListener thus leaking it. Later when an interruption was received the THIS_ object would contain a pointer to an already released device causing the crash.

The fix:
When only one device remained open and it was being closed we needed to set the audio session as NOT active and completely ignore the returned error to successfully release the SDLInterruptionListener. I think the user assumed that the open_playback_devices and open_capture_devices would equal 0 when all of them where closed but the truth is that at the end of the closing process that the open devices count is decremented.

Here is our fix in github:
jonameson/SDL-mirror@1d96bd6

I apologize that I'm unable to provide a patch. I'm not too familiar with the process. I hope this helps.

On 2018-05-24 14:26:43 +0000, Sam Lantinga wrote:

It looks like the latest SDL in Mercurial may have already resolved this, as it contains a similar change to that patch. Can you take a look?
http://www.libsdl.org/tmp/SDL-2.0.zip

Thanks!

On 2018-05-24 20:33:21 +0000, Jona wrote:

That fix is good! It's a little clearer than my fix.

On 2018-05-25 19:27:03 +0000, Sam Lantinga wrote:

Great, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant