Daniel Beer Atom | RSS | Contact

Linux Bluetooth audio bug fixes

26 Jan 2026

Assorted bugs found while working on Bluetooth audio on an embedded Linux system. Two of these patches are bugs in PulseAudio which have not been applied upstream.

PulseAudio 17.0: Double-close of file descriptor in backend-ofono

Issue 3811 - This patch has not been applied upstream.

While testing a system that used oFono for telephony and the PulseAudio oFono backend, we noticed that PulseAudio would sometimes (perhaps 20% of the time) crash or behave strangely at the end of a phonecall. There were a variety of different symptoms. A particularly common symptom was a system call failing with “Invalid file descriptor” or POLLNVAL.

Running PulseAudio under strace showed shutdown() being called at the end of a phonecall on a file descriptor which was not a socket. I eventually noticed that the file descriptor obtained by calling acquire on the backend transport was closed by the Bluetooth device module, but it was also being closed by release in the oFono backend (but not the native backend, which seemed to work fine). Since PulseAudio is multi-threaded with new file descriptors being created and fd numbers recycled in different threads, this kicks off a chain of unpredictable behaviour.

The attached patch fixed the issue. I simply make the assumption that acquire means that the returned file descriptor has changed ownership and now belongs to the caller. As far as I know, this patch is ok to be applied as-is, but any feedback would be appreciated.

PulseAudio 17.0: SBC decoding errors cause IO thread to terminate

Issue 3819 - This patch has not been applied upstream.

I noticed while working on an embedded project that occasionally we’d get SBC decoding errors while streaming from an A2DP source device. These caused the IO thread to terminate. Of course they should not normally occur, but it turns out that they need not be fatal, and simply ignoring the error leads to the next frame being processed correctly and the audio continuing with only a minor interruption (see attached patch).

I’m not sure what the cause is for the SBC decoding errors, but I suspect it may be due to multiple packets being backed up in the receive queue. The way the code is written, it doesn’t look like the reader expects to receive more than one frame on each POLLIN event.

BlueZ 5.78: Resource leak in A2DP profile handling, requiring restart

Mailing list - These patches have been applied in BlueZ 5.79.

If the stream goes IDLE while we have an outstanding request, connect_id stays non-zero and is never cleared via a completion callback. As a consequence, the profile on this device will never be connected successfully again until BlueZ restarts.