Deadlock when receiving GATT notifications and remote device disconnects
Closed this issue · 4 comments
var char gatt.GattCharacteristic1 = GetMyGattCharacteristic1()
if chan, err = char.WatchProperties(); err != nil {
return
}
if err := char.StartNotify(); err != nil {
return
}
// do work
// remote device dies
if err := light.notifyCharacteristic.StopNotify(); err != nil {
log.Error("failed to stop notifications from light")
}
if err := light.notifyCharacteristic.UnwatchProperties(light.propertyChangedChan); err != nil {
log.Error("failed to stop watching notifications")
}
// reconnect
// reconnection successful
var char gatt.GattCharacteristic1 = GetMyGattCharacteristic1()
if chan, err = char.WatchProperties(); err != nil {
return
}
The last char.WatchProperties()
will never return.
This due to the fact that the goroutine in github.com/godbus/dbus.(*defaultSignalHandler).DeliverSignal
will keep waiting for data coming from a channel because that channel is never closed. Doing so it will never release a lock that is held, causing a deadlock when WatchProperties
is called again.
The channel is never closed because while bluez.props.WatchProperties
will call bluez.client.Register
, which in turn will set up a signal channel calling c.conn.Signal(channel)
, bluez.props.UnwatchProperties
never calls bluez.client.Unregister
, or in general it won't call c.conn.RemoveSignal(signal)
, which closes that channel and frees that goroutine.
Hi @depau
I have a dev branch which is mostly updated but poorly tested yet. If you want to give it a shot it is app_refactor
.
I think I broke the service
exposing implementation, but the rest should be up to date
Hi,
I tried with the app_refactor
branch but the deadlock is still occurring. I'll try to see why in the next days.
Thanks, that branch is merged into master now. Please ensure to run make all
as the library need to generate code from the bluez API docs.
Closing, please reopen if needed.