IanHarvey / bluepy

Python interface to Bluetooth LE on Linux
Other
1.6k stars 490 forks source link

writeCharacteristic() not thread safe with waitForNotifications() #349

Open ronnymajani opened 5 years ago

ronnymajani commented 5 years ago

In the following code snippet:

def writeCharacteristic(self, handle, val, withResponse=False):
        # Without response, a value too long for one packet will be truncated,
        # but with response, it will be sent as a queued write
        cmd = "wrr" if withResponse else "wr"
        self._writeCmd("%s %X %s\n" % (cmd, handle, binascii.b2a_hex(val).decode('utf-8')))
        return self._getResp('wr')

When using multithreading, if one thread is using peripheral.waitForNotifications(), and another thread calls characteristic.write(somevalue, withResponse=False), it's possible that the response value 'wr' that writeCharacteristic is expecting gets 'missed' because it gets propagated to waitForNotifications() instead, and therefore the call to writeCharacteristic() will block indefinitely.

One possible workaround is to set withResponse=True, which will "queue" the write request I think (not exactly sure what the implications of this are as I didn't go any deeper). Anyway just thought it would be good to point this out if anyone ever gets stuck on the same point or is wondering why their threads are getting stuck :smile:

ronnymajani commented 5 years ago

I think this is also explains the behavior in #253

sterwen commented 5 years ago

The whole btle.py module is not thread safe. So the thread safety needs to be worked elsewhere