muka / go-bluetooth

Golang bluetooth client based on bluez DBus interfaces
Apache License 2.0
653 stars 124 forks source link

Discover never returns #122

Closed MGasztold closed 4 years ago

MGasztold commented 4 years ago

I have an issue with my application that locks on Discover method .

It happens after several minutes of performing a cycled scanning (start scan, sleep 2 seconds, stop scan, sleep 1 second). When it happens the goroutine handling the scanning is locked forever on a start scanning attempt, on the line of code in which I call api.Discover method.

I tried doing some retry logic by putting the calls to Discover method in goroutine and continuing with next scan cycle after few seconds. This makes the app never stuck and when e.g. I replug my BLE HCI dongle the app smoothly starts working well again. However I am afraid that It is not a good approach because it generates memory leaks because launched goroutines are left unfinished and i am not sure they are gonna be handled by GC.

Did anybody have this issue and is there any solution? Thanks.

muka commented 4 years ago

Hi the second return from Discover is a cancel function. Have you tried using it?

Can you post some code to reproduce?

Thanks

MGasztold commented 4 years ago

I start the scanning with the code pasted below. I cannot leverage cancel function because the program locks on api.Discover(self.Adapter, &filter), it does not return. It seems like the problem is somewhere deeper than go-bluetooth, e.g. maybe my BLE HCI dongle causes problems ?

Sometimes my program runs for many hours without problems but eventually the lock on api.Discover(self.Adapter, &filter) always happens and to solve it i need to replug the BLE HCI dongle and restart my process.


 * Start BLE scanning
 */
func (self *UBBleAdapter) ScanStart() error {
    if self.Scanning == true {
        return nil
    }
    self.Adapter.FlushDevices()
    self.FilteredMacs = make(map[string]bool, 0)

    filter := adapter.NewDiscoveryFilter()
    filter.DuplicateData = true
    filter.Transport = adapter.DiscoveryFilterTransportLE
    discovery, cancel, err := api.Discover(self.Adapter, &filter)
    if err != nil {
        return err
    }
    self.ScanResultCh = discovery
    self.ScanCancelFn = cancel
    self.Scanning = true
    go self.scanResultHandler()

    return nil
}```