Skip to content

Make sure FilterAudioStream is alive in callbacks (#2325)#2354

Open
jg-hot wants to merge 1 commit intogoogle:mainfrom
jg-hot:FilterAudioStream-fix
Open

Make sure FilterAudioStream is alive in callbacks (#2325)#2354
jg-hot wants to merge 1 commit intogoogle:mainfrom
jg-hot:FilterAudioStream-fix

Conversation

@jg-hot
Copy link
Copy Markdown

@jg-hot jg-hot commented Mar 21, 2026

This modifies AAudioStreamCollection.getStream() to return a tuple which includes a shared_ptr to the parent stream if the AAudioStream is wrapped by a FilterAudioStream.

The child is linked to the parent via a raw pointer (AudioStream.getParentStream() / AudioStream.hasParentStream() and locked during callbacks with lockWeakThis().

The shared_ptr to the parent is passed to the callback threads (e.g. oboe_aaudio_error_thread_proc_shared) so its memory is retained until the callback thread finishes running.

See discussion under issue #2325 for more details.

Tested against the sample in FilterAudioStreamUAF-repro.

@jg-hot
Copy link
Copy Markdown
Author

jg-hot commented Mar 21, 2026

@flamme @robertwu1 could you please review this when you get a chance? I'm not able to add reviewers directly. Thanks.

@robertwu1 robertwu1 requested review from flamme and robertwu1 March 23, 2026 18:48
@robertwu1
Copy link
Copy Markdown
Collaborator

LGTM @flamme please add comments if you have any. Thanks!

// callbacks are routed through it.
std::shared_ptr<AudioStream> sharedParentStream;
if (sharedStream && sharedStream->hasParentStream()) {
sharedParentStream = sharedStream->getParentStream()->lockWeakThis();
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Q: this parent stream is a raw pointer, how it guarantees the parent stream is still alive when a callback arrive?

Copy link
Copy Markdown
Author

@jg-hot jg-hot Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This relies on the same assumption that the AAudioStreamCollection uses for the child (AAudio) stream. That the client always calls close() before releasing their shared_ptr.

That ensures that callbacks are rejected if the stream is about to be released.

The parent should be alive as long as the child is. The ownership chain is shared_ptr client → FilterAudioStreamAudioStreamAAudio.

I don't see any case where the parent is freed but the child is not.

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

Successfully merging this pull request may close these issues.

3 participants