bluetooth: fix race condition in BlueZ5 device disconnection
authorJuha Kuikka <juha.kuikka@synapse.com>
Sat, 16 Apr 2016 00:37:22 +0000 (17:37 -0700)
committerTanu Kaskinen <tanuk@iki.fi>
Mon, 28 Nov 2016 11:17:44 +0000 (13:17 +0200)
commit6a786c93758b9cf2128938a8459c3387c0532a1e
tree36693ddf1ef9ba6e0a89f0028ce00d288099ccb7
parent6c99c2a278dfe568a53cc3bbc4312d66b9b6570e
bluetooth: fix race condition in BlueZ5 device disconnection

SW: Pulseaudio 8.0 / BlueZ 5.39

Symptoms:
While disconnecting/reconnecting a paired bluetooth headset (LG HBS750)
audio fails roughly on every other connection.

On a failed connection "pactl list cards" shows the bluetooth device's
card but "Active Profile: off". Issuing "pacmd set-card-profile X
a2dp_sink" makes audio work immediately.

I realized that when this happened, the previous disconnection did not
remove the card, instead it was only configured for "Active Profile:
off" but otherwise left in place.

Upon looking at PA debug logs I saw that the transport for the a2dp_sink
was first set into disconnected state and then into idle state. In
"device_connection_changed_cb()" this causes the
"pa_bluetooth_device_any_transport_connected()" return true and the
module-bluez5-device is not unloaded.

Further investigation shows that this is caused by a race of
module-bluez5-device.c:thread_func() and
MediaPoint1::ClearConfiguration().

When the FD in thread_func() is closed (POLLHUP) an
BLUETOOTH_MESSAGE_STREAM_FD_HUP message is sent into the main thread.
The handler of this message unconditionally sets the transport into IDLE
state. This is a problem if it has already been set into DISCONNECTED
state.
src/modules/bluetooth/module-bluez5-device.c