-
Notifications
You must be signed in to change notification settings - Fork 7.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
deleting BLEClient is not safe #4047
Comments
From what I tested, you have to wait until client->isConnected returns false before you can delete it. I added a spinloop which checks every 50ms before deleting. Caching and reusing may work, but it did not work for me when I tried to use the same instance to reconnect to different devices. |
BLEClient is deleted inside library after disconnecting. |
oh? is it a recent change? |
No, its been added months ago, before BLE library has been merged. |
I have just had this issue also. It turns out that GATTC_DISCONNECT (and other events) are propagated to ALL clients, not just the one that disconnected. Fix is in #4055 - my multi-client code has been pretty stable since i applied it. |
Hmm. Looking at the BLEClient code a bit more. I think that maybe adding a But Together with what @yongkimleng and @buxtronix found this means that you can never delete the BLEClient, and moreover there may always be "ghost callbacks from past connections" when you reuse the BLEClient. |
The 'ghost callbacks' I've been seeing (addressed in #4064) happen even when no connection was ever closed (ie two new clients connecting after a reboot). Something to note (maybe two issues here?) |
You probably ran into this problem: #3973 |
No, #3973 is about cleanup with deleted clients. The problem I have seen is with new connections after boot, before any disconnect event has occurred (but also happens on disconnect, but this is for similar reasons relating to bad callbacks ). |
[STALE_SET] This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs. Thank you for your contributions. |
[STALE_DEL] This stale issue has been automatically closed. Thank you for your contributions. |
The BLEClient multi connect implementation is still buggy. I started with reusing and reconnecting multiple BLEClients but it requires at least the following fix in "gattClientEventHandler" or something equivalent:
This because upon disconnection BLEClients aren't properly cleaned up. I tried also to use a new BLEClient each time I need a connection but BLEClient deletion is even more buggy. |
Any reason why the disconnect client callback is before all the cleanup ?
|
Cleanup before calling disconnect callback for safe delete. Reject other events during registration. Adresses espressif#4047, espressif#4055
Probably its my mistake. |
I think I've reached some degree of stability in my fork. I've been running some re-connection tests in my wannabe BLE gateway development and it seems to be fine so far with very little memory fragmentation. My client does the following:
Sometimes the device connection fails (device is in a metal encosure and at some distance) and the automatic retry kicks in, this reuses the same BLEClient and seems to work fine. Sometimes the device disconnects randomly, the BLE gateway deletes the BLEClient uppon disconnection so that also works fine. I've been running this for the past 30 min, there is still some memory fragmentation from time to time that I can't quite pinpoint yet and I'm not sure if it will be possible to do anything about it. This does not happen after each re-connection cycle but once in a while the UPDATE: after about 1h of this, WiFiClient failed :D
|
The NimBLE implementation seems more stable and a whole lot more memory efficient (saves about 70K RAM and 400K flash) and is more suitable for my use case. |
@kind3r Your wifi/ble gateway looks interesting, I have already implemented an udp/ble gateway and I ended up using NimBLE because there was no way to let multi clients work. |
I have not tested multiple clients yet but after the fixes I made to BLE lib I see no reason why it should not be working. My tests basically do the connect/reconnect/disconnect etc. on one device but with a new BLEClient each time. So applying the same techinique to multiple different devices should be fine, as long as there is a limit implemented on the simultaneous connections. Nevertheless, I think the RAM constraints would prevent more than 3 connections at a time, which is neither needed for my project nor practical as BLE sessions should be kept short to save the battery on the devices. Still, with NimBLE there is a lot of room for more connections and other stuff that I want to implement. |
- Remove client from the list of devices in case registration fails - Filter other events not related to registration during registration phase - Cleanup if connect fails - Reset if after disconnect - Disconnect callback *after* cleanup is done so object can be deleted This fixes some of the issues I had like: - `BLEClient::connect` hangs up and never recovered because registration failed - `BLEClient` could not be deleted after disconnect or deletion creating ghost events #4047 - `BLEClient` could not be properly reused after a connection was attempted (successful or not) * Cleanup in case of registration and connect failure. Cleanup before calling disconnect callback for safe delete. Reject other events during registration. Adresses #4047, #4055 * Clear if after unregister #4047
My BLE client code was structured more-or-less as
but this is unsafe. Sometimes I get a corrupted heap, sometimes I get other crashes, possibly after running this code again (I am creating many connections to many BLE devices over a long time).
I think the problem may be that
disconnect()
is asynchronous, because often my crashes are inBLEClient::gattClientEventHandler()
in theESP_GATTC_DISCONNECT_EVT
case handler, but they can also happen in the BLE thread, or in completely unrelated code.The workaround I have is to never delete my BLEClient objects but to cache and reuse them, but from the code (and the minimal documentation) it seems like I should have been able to create and delete them on-the-fly.
The text was updated successfully, but these errors were encountered: