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 protected]> 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 protected])
> Help/Unsubscribe/Update your Subscription:
> https://lists.apple.com/mailman/options/coreaudio-api/arwyn%40phasic.com
> 
> This email sent to [email protected]

 _______________________________________________
Do not post admin requests to the list. They will be ignored.
Coreaudio-api mailing list      ([email protected])
Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/coreaudio-api/archive%40mail-archive.com

This email sent to [email protected]

Reply via email to