diff --git a/subsys/mgmt/mcumgr/transport/smp_bt.c b/subsys/mgmt/mcumgr/transport/smp_bt.c index 0cac7736c7de..f963b4aa35d7 100644 --- a/subsys/mgmt/mcumgr/transport/smp_bt.c +++ b/subsys/mgmt/mcumgr/transport/smp_bt.c @@ -387,6 +387,7 @@ static int smp_bt_tx_pkt(struct net_buf *nb) .data = nb->data, }; bool sent = false; + struct bt_conn_info info; conn = smp_bt_conn_from_pkt(nb); if (conn == NULL) { @@ -394,6 +395,22 @@ static int smp_bt_tx_pkt(struct net_buf *nb) goto cleanup; } + /* Verify that the device is connected, the necessity for this check is that the remote + * device might have sent a command and disconnected before the command has been processed + * completely, if this happens then the the connection details will still be valid due to + * the incremented connection reference count, but the connection has actually been + * dropped, this avoids waiting for a semaphore that will never be given which would + * otherwise cause a deadlock. + */ + rc = bt_conn_get_info(conn, &info); + + if (rc != 0 || info.state != BT_CONN_STATE_CONNECTED) { + /* Remote device has disconnected */ + bt_conn_unref(conn); + rc = MGMT_ERR_ENOENT; + goto cleanup; + } + /* Send data in chunks of the MTU size */ mtu_size = smp_bt_get_mtu(nb); @@ -414,7 +431,6 @@ static int smp_bt_tx_pkt(struct net_buf *nb) notify_param.len = mtu_size; rc = bt_gatt_notify_cb(conn, ¬ify_param); - k_sem_take(&smp_notify_sem, K_FOREVER); if (rc == -ENOMEM) { if (sent == false) { @@ -443,7 +459,10 @@ static int smp_bt_tx_pkt(struct net_buf *nb) off += mtu_size; notify_param.data = &nb->data[off]; sent = true; + + k_sem_take(&smp_notify_sem, K_FOREVER); } else { + /* No connection, cannot continue */ rc = MGMT_ERR_EUNKNOWN; break; }