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:
Timothy Keys 2024-12-04 12:14:35 +00:00 committed by Benjamin Cabé
commit b3ffaf4441

View file

@ -1254,6 +1254,11 @@ void bt_conn_set_state(struct bt_conn *conn, bt_conn_state_t state)
*/
switch (old_state) {
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_reset_rx_state(conn);