Hi, On Wednesday, 18 August 2021 21:38:32 CEST Jeremy Cole-Baker wrote: > Hi, > > We are using Nimble BLE on an Espressif ESP32 project. We are getting > frequent crashes due to invalid memory access. It looks like a race > condition / threading issue to me, but I can't find much info about using > Nimble from different threads (i.e. different tasks in FreeRTOS). > > Here's a typical crash log: > > 0x4012773f: put_le16 at > C:/Users/Jeremycb/esp-idf/components/bt/host/nimble/nimble/porting/nimble/s > rc/endian.c:24 0x400e77c5: ble_hs_hci_cmd_send at > C:/Users/Jeremycb/esp-idf/components/bt/host/nimble/nimble/nimble/host/src/ > ble_hs_hci_cmd.c:77 0x400e7819: ble_hs_hci_cmd_send_buf at > C:/Users/Jeremycb/esp-idf/components/bt/host/nimble/nimble/nimble/host/src/ > ble_hs_hci_cmd.c:122 0x400e3611: ble_hs_hci_cmd_tx at > C:/Users/Jeremycb/esp-idf/components/bt/host/nimble/nimble/nimble/host/src/ > ble_hs_hci.c:304 0x400e386b: ble_hs_hci_util_read_rssi at > C:/Users/Jeremycb/esp-idf/components/bt/host/nimble/nimble/nimble/host/src/ > ble_hs_hci_util.c:96 0x400e1709: ble_gap_conn_rssi at > C:/Users/Jeremycb/esp-idf/components/bt/host/nimble/nimble/nimble/host/src/ > ble_gap.c:5906 0x400dc0d5: RSSIUpdateTask at > C:\Users\Jeremycb\esp\wireless-controller\build/../components/wc_bluetooth/ > wc_ble_services.c:369 0x40092e39: vPortTaskWrapper at > C:/Users/Jeremycb/esp-idf/components/freertos/port/xtensa/port.c:168 > > It looks like a bad pointer (NULL) passed to "put_le16". > > I've seen 3 different call paths, 2 from my own tasks and one from the task > used to start / run Nimble. They all converge at the function > "ble_hs_hci_cmd_send_buf", which then calls "ble_hs_hci_cmd_send" > > "ble_hs_hci_cmd_send" uses "ble_hci_trans_buf_alloc", but looking at the > code for the "BLE_HCI_TRANS_BUF_CMD" option, there is only one buffer > available, and the comments say that "The controller will only allow one > outstanding command". Thus it returns NULL if called from different > threads, and results in the crash. > > Looking through the call paths, I see that we can get there two ways: > "ble_hs_hci_cmd_tx" (called from our code and many other places) or > "ble_hs_flow_tx_num_comp_pkts" (called from flow event callback, from BLE > host task). > > I looked for a mutex, and found that "ble_hs_hci_cmd_tx" locks > ble_hs_hci_mutex, whereas "ble_hs_flow_event_cb" (called by BLE host task) > locks ble_hs_mutex (different). > > Our code is calling "ble_gap_conn_rssi" and "ble_gap_adv_rsp_set_fields" on > different tasks / threads, which ultimately call "ble_hs_hci_cmd_tx". > > So, it looks like it's NOT SAFE to call these functions on another thread. > This looks like a bug, otherwise how would these functions be used? >
For the record, this will be handled by https://github.com/apache/mynewt-nimble/pull/1012 -- pozdrawiam Szymon Janc