From 6ee2c1025b67ed5073760a83c05abe3cc69e7b1c Mon Sep 17 00:00:00 2001 From: Hauke Petersen Date: Thu, 3 Sep 2020 11:42:08 +0200 Subject: [PATCH] pkt/nimble/netif: fix deadlock on connection loss --- pkg/nimble/netif/include/nimble_netif_conn.h | 12 ++++++++++++ pkg/nimble/netif/nimble_netif.c | 10 +++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/pkg/nimble/netif/include/nimble_netif_conn.h b/pkg/nimble/netif/include/nimble_netif_conn.h index ede164def9..d1cd7f4432 100644 --- a/pkg/nimble/netif/include/nimble_netif_conn.h +++ b/pkg/nimble/netif/include/nimble_netif_conn.h @@ -216,6 +216,18 @@ static inline int nimble_netif_conn_connected(const uint8_t *addr) return (nimble_netif_conn_get_by_addr(addr) != NIMBLE_NETIF_CONN_INVALID); } +/** + * @brief Test if the given connection is (still) open + * + * @param[in] conn Connection to test + * + * @return != 0 if true + * @return 0 if false + */ +static inline int nimble_netif_conn_is_open(const nimble_netif_conn_t *conn) +{ + return (conn->coc != NULL); +} /** * @brief Convenience function to check if any context is currently in the diff --git a/pkg/nimble/netif/nimble_netif.c b/pkg/nimble/netif/nimble_netif.c index 4dc5f6b28a..1331d07c95 100644 --- a/pkg/nimble/netif/nimble_netif.c +++ b/pkg/nimble/netif/nimble_netif.c @@ -62,6 +62,8 @@ /* thread flag used for signaling transmit readiness */ #define FLAG_TX_UNSTALLED (1u << 13) +#define FLAG_TX_NOTCONN (1u << 12) +#define FLAG_ALL (FLAG_TX_UNSTALLED | FLAG_TX_NOTCONN) /* allocate a stack for the netif device */ static char _stack[THREAD_STACKSIZE_DEFAULT]; @@ -130,7 +132,11 @@ static int _send_pkt(nimble_netif_conn_t *conn, gnrc_pktsnip_t *pkt) do { res = ble_l2cap_send(conn->coc, sdu); if (res == BLE_HS_EBUSY) { - thread_flags_wait_all(FLAG_TX_UNSTALLED); + thread_flags_t state = thread_flags_wait_any(FLAG_ALL); + /* abort if the active connection was lost in the mean time */ + if ((state & FLAG_TX_NOTCONN) && !nimble_netif_conn_is_open(conn)) { + return -ECONNRESET; + } } } while (res == BLE_HS_EBUSY); @@ -455,6 +461,7 @@ static int _on_gap_master_evt(struct ble_gap_event *event, void *arg) : NIMBLE_NETIF_ABORT_MASTER; uint8_t addr[BLE_ADDR_LEN]; nimble_netif_conn_free(handle, addr); + thread_flags_set(_netif_thread, FLAG_TX_NOTCONN); _notify(handle, type, addr); break; } @@ -498,6 +505,7 @@ static int _on_gap_slave_evt(struct ble_gap_event *event, void *arg) : NIMBLE_NETIF_ABORT_SLAVE; uint8_t addr[BLE_ADDR_LEN]; nimble_netif_conn_free(handle, addr); + thread_flags_set(_netif_thread, FLAG_TX_NOTCONN); _notify(handle, type, addr); break; }