Re: trouble recording from Bluetooth microphone
Re: trouble recording from Bluetooth microphone
- Subject: Re: trouble recording from Bluetooth microphone
- From: Ed Wynne via Coreaudio-api <email@hidden>
- Date: Wed, 20 Nov 2019 15:08:47 -0500
Hamish,
TL;DR; This isn’t you, it’s Apple. Bluetooth audio devices have become very
unreliable in recent macOS versions. It is affecting a lot of 3rd party apps.
If you want a longer, better explanation, based on my debugging and
guesswork... The timeline of what produces those logging messages goes
something like this:
- App calls AudioDeviceStart
- AudioDeviceStart (in CoreAudio.framework) makes RPC to coreaudiod to start
the audio device context
- coreaudiod successfully starts the audio device context — part of which
is a separate asynchronous processing thread that drives the audio IO
Now, this is where it gets interesting… two things have to happen to cause the
BT problems you are seeing:
1) - Before the RPC to coreaudiod can return to the calling app context, it
gets preempted — there is nothing wrong with this, it just means the calling
app context won’t know the audio device context has been started until a small
arbitrary bit of time later
2) - When a BT audio device context is started, it needs to configure the BT
device profile (I might not have the correct terminology here, I’m not really
up on BT specifics). When the BT audio device is already in the right device
profile, this happens fast and successfully, and the audio context begins
normal operation. However, when the BT device is not configured correctly,
something seems to go wrong on the first attempt to reconfigure it.
Additionally, and I have no idea why, if you play/stop, play/stop, play/stop,
etc., a couple of times, it always very quickly leads to a situation where the
BT device needs to be reconfigured. When whatever the BT configuration thing is
that goes wrong, actually goes wrong, the audio device context is
aborted/stopped and context starts to get torn down.
However, it is important to keep in mind, this is all happening on the
asynchronous processing thread. It is running concurrently to the
AudioDeviceStart (in CoreAudio.framework) waiting for the RPC call to return in
the app context. There seems to be a rather ugly race condition here as really
bad things happen if the RPC call returns while the audio device context is in
the process of being torn down.
The code in AudioDeviceStart thinks the audio device context has started, it
has no idea the context is actually in some state of being torn down, and it
happily goes on to initialize the application side things. Such as attempting
to map a shared memory window for the audio buffers. That memory window was
setup by coreaudiod, but may be gone already. Or worse, it may be in the
process of going away. So the mapping might fail. Or worse, it might succeed,
but then almost immediately get orphaned. The same kinds of things happen for
various ports and other context items.
It is this app side initialization concurrent to while the server side is going
away that is causing the logging failures and problems we are all seeing with
BT devices. If the RPC from coreaudiod returns really fast, the app side gets
setup before the audio device context starts its tear down, and nothing bad
happens. Or if the RPC from coreaudiod returns slow enough, the audio device
context is already gone, then the app side seems to fail cleanly. In both of
these cases, the start is retried and always seems to work properly the second
time.
You have to be unlucky enough for the timing to work out just right, then Boom.
You get strange errors, corruption, etc., and no retry. Some people see this
all the time, and it is highly reproducible for them. Other people never see
it. That is the beauty of a heisenbug like this. It is purely based on timing.
Well, timing and a lack of synchronization in CoreAudio. It seems to suffer
from a lot of race conditions like this.
-Ed
> On Nov 18, 2019, at 9:10 PM, Hamish Moffatt via Coreaudio-api
> <email@hidden> wrote:
>
> Hi,
>
> For the last week I've been debugging random crashes in our application when
> recording from a Bluetooth headset. I've tidied up lots of code including
> fixing allocations from the callback thread, and it's more stable, but I
> still have an occasional crash.
>
>
> When I start recording (by calling AudioOutputUnitStart) I often get the
> following error printed:
>
> testWavein[3983:4356913] [AudioHAL_Client]
> HALB_SharedBuffer.cpp:110:Allocate_Client:
> HALB_SharedBuffer::Allocate_Client: failed to open the connection to the
> shared memory object
>
>
> What does this error mean?
>
> This error, and all my crashing, only happens with Bluetooth headsets
> (Airpods and others). I'm not sure if the message is relevant but I'm
> stumped and don't want to overlook anything. The crashes, when they occur,
> are memory corruption type errors in random parts of the code on unrelated
> threads - often in the UI.
>
>
> Hamish
>
> _______________________________________________
> Do not post admin requests to the list. They will be ignored.
> Coreaudio-api mailing list (email@hidden)
> Help/Unsubscribe/Update your Subscription:
>
> This email sent to email@hidden
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Coreaudio-api mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden