Bluetooth: Host: Cancel pending deferred work on disconnect
This fixes an issue that occurred if deferred_work is queued by another procedure before we run bt_conn_set_state(BT_CONN_DISCONNECTED). bt_conn_set_state yields to the system work queue in bt_conn_tx_notify, and then deferred_work runs and handles the disconnected callbacks. bt_conn_set_state then enqueues another deferred_work which calls the disconnected callbacks again and causes an assert. k_work_cancel_delayable will clear queued deferred work when we call bt_conn_set_state(BT_CONN_DISCONNECTED), guaranteeing that the disconnect callbacks will only be called once. Signed-off-by: Timothy Keys <timothy.keys@nordicsemi.no>
This commit is contained in:
parent
4c96cbb79b
commit
b3ffaf4441
1 changed files with 5 additions and 0 deletions
|
@ -1254,6 +1254,11 @@ void bt_conn_set_state(struct bt_conn *conn, bt_conn_state_t state)
|
||||||
*/
|
*/
|
||||||
switch (old_state) {
|
switch (old_state) {
|
||||||
case BT_CONN_DISCONNECT_COMPLETE:
|
case BT_CONN_DISCONNECT_COMPLETE:
|
||||||
|
/* Any previously scheduled deferred work now becomes invalid
|
||||||
|
* so cancel it here, before we yield to tx thread.
|
||||||
|
*/
|
||||||
|
k_work_cancel_delayable(&conn->deferred_work);
|
||||||
|
|
||||||
bt_conn_tx_notify(conn, true);
|
bt_conn_tx_notify(conn, true);
|
||||||
|
|
||||||
bt_conn_reset_rx_state(conn);
|
bt_conn_reset_rx_state(conn);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue