NimBLE-Arduino icon indicating copy to clipboard operation
NimBLE-Arduino copied to clipboard

NimBLEDevice::deinit() causing crash on 2.3.2

Open justcallmekoko opened this issue 4 months ago • 14 comments

I encountered an issue with a bit of code I had not had issues with in much earlier versions of NimBLE, such as 1.3.8 for example. I have created this small sketch to cleanly demonstrate the issue I am experiencing. I am running this on an ESP32-C5-DevKitC-1 v1.2 on Arduino-ESP32 v3.3.0 with NimBLE-Arduino v2.3.2.

The goal with this sketch is to simply initialize NimBLE, prepare a scan callback method that doesn't actually do anything, then deinitialize NimBLE. In the past, this has not been an issue but on 2.3.2, it seems to cause a crash (see Serial Output below).

#include <Arduino.h>
#include <NimBLEDevice.h>

NimBLEScan* pBLEScan;

// ⚠️ Define the callback object statically
class scanCallbacks : public NimBLEScanCallbacks {
  void onDiscovered(const NimBLEAdvertisedDevice* advertisedDevice) override {
    // No-op
  }
};
scanCallbacks bleCallback;  // <-- static global, never delete

void deinitBLE() {
  Serial.println("Deinitializing BLE...");

  if (pBLEScan != nullptr) {
    if (pBLEScan->isScanning()) {
      Serial.println("Stopping BLE scan...");
      pBLEScan->stop();
      while (pBLEScan->isScanning()) {
        delay(10);
      }
    }

    Serial.println("Clearing results...");
    pBLEScan->clearResults();

    Serial.println("Unbinding callbacks...");
    pBLEScan->setScanCallbacks(nullptr);  // Detach only, DO NOT delete

    delay(10);  // Let BLE stack catch up
  }

  NimBLEDevice::deinit();
  Serial.println("Finished deinitializing BLE");
}

void initBLE() {
  NimBLEDevice::init("demo");
  pBLEScan = NimBLEDevice::getScan();

  pBLEScan->setScanCallbacks(&bleCallback, false);  // Use address of static object
  pBLEScan->setActiveScan(true);
  pBLEScan->setDuplicateFilter(false);
  pBLEScan->setMaxResults(0);
}

void setup() {
  Serial.begin(115200);
  while (!Serial) delay(10);

  initBLE();
  Serial.println("Init BLE complete");

  delay(1000);

  deinitBLE();
  Serial.println("Deinit BLE complete");
}

void loop() {}

Serial Output

17:06:09.978 -> Init BLE complete
17:06:10.964 -> Deinitializing BLE...
17:06:10.964 -> Clearing scan results...
17:06:10.964 -> Releasing scan callbacks...
17:06:10.964 -> CORRUPT HEAP: Bad tail at 0x4085c834. Expected 0xbaad5678 got 0xba000000
17:06:10.964 -> 
17:06:10.997 -> assert failed: multi_heap_free multi_heap_poisoning.c:279 (head != NULL)
17:06:10.997 -> Core  0 register dump:
17:06:10.997 -> MEPC    : 0x408007ec  RA      : 0x4080dd28  SP      : 0x4085ed10  GP      : 0x40814c84  
17:06:11.031 -> TP      : 0x4085ef60  T0      : 0x37363534  T1      : 0x7271706f  T2      : 0x33323130  
17:06:11.031 -> S0/FP   : 0x00000001  S1      : 0x4085ee88  A0      : 0x4085ed74  A1      : 0x4081694d  
17:06:11.031 -> A2      : 0x00000001  A3      : 0x00000029  A4      : 0x00000001  A5      : 0x4081a000  
17:06:11.064 -> A6      : 0x0000000c  A7      : 0x76757473  S2      : 0x0000007f  S3      : 0x4085ed68  
17:06:11.064 -> S4      : 0x4085ed68  S5      : 0x4085ed74  S6      : 0x00000000  S7      : 0x00000000  
17:06:11.064 -> S8      : 0x00000000  S9      : 0x00000000  S10     : 0x00000000  S11     : 0x00000000  
17:06:11.064 -> T3      : 0x6e6d6c6b  T4      : 0x6a696867  T5      : 0x66656463  T6      : 0x62613938  
17:06:11.064 -> MSTATUS : 0x00001881  MTVEC   : 0x40800003  MCAUSE  : 0x00000002  MTVAL   : 0x00000000  
17:06:11.097 -> MHARTID : 0x00000000  
17:06:11.097 -> 
17:06:11.097 -> Stack memory:
17:06:11.097 -> 4085ed10: 0x00000000 0x00000000 0x4209d770 0x408127b4 0xffffffff 0x00000046 0x0000000a 0x4081694c
17:06:11.097 -> 4085ed30: 0x4085eda0 0x00000018 0x40827858 0x00393732 0xffffffff 0x40816934 0x4209d770 0x40816dd0
17:06:11.097 -> 4085ed50: 0x420952fe 0x40816944 0x4085ed3c 0x40816948 0x420952d8 0x4081694c 0x00000000 0x00000000
17:06:11.097 -> 4085ed70: 0x00000000 0x65737361 0x66207472 0x656c6961 0x6d203a64 0x69746c75 0x6165685f 0x72665f70
17:06:11.131 -> 4085ed90: 0x6d206565 0x69746c75 0x6165685f 0x6f705f70 0x6e6f7369 0x2e676e69 0x37323a63 0x68282039
17:06:11.131 -> 4085edb0: 0x20646165 0x4e203d21 0x294c4c55 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000
17:06:11.131 -> 4085edd0: 0x4081a000 0x00000001 0x4085c828 0x4001db2c 0x4085ef60 0x40020d0c 0x42029cca 0x00000200
17:06:11.131 -> 4085edf0: 0x408224e8 0x00000000 0x0000001f 0x4085ee14 0x00000001 0xf7000002 0x00000000 0x40812430
17:06:11.164 -> 4085ee10: 0xfff00000 0x4085c834 0xbaad5678 0xba000000 0x4081a000 0xba000000 0xfff00000 0x00000000
17:06:11.164 -> 4085ee30: 0x00000000 0x00000000 0x00000000 0xbc0abd07 0x40860000 0x00000000 0x00000000 0x00000000
17:06:11.164 -> 4085ee50: 0x4081a000 0x4085c830 0x4085c5a0 0x408121fe 0x4081a000 0x4081a000 0x40821fa8 0x420403a6
17:06:11.164 -> 4085ee70: 0x4081a000 0x4081a000 0x4081a4b0 0x42045184 0x4081a000 0x00000000 0x206d0000 0x42030008
17:06:11.197 -> 4085ee90: 0x4081a000 0x00000000 0x206d0000 0x4204c8f8 0x4081a000 0x00000000 0x40816000 0x42029984
17:06:11.197 -> 4085eeb0: 0x4081a000 0x00000000 0x00000000 0x42013c36 0x4081a000 0x00000000 0x00000000 0x42001644
17:06:11.197 -> 4085eed0: 0x40860000 0x4081ddcc 0x4081a680 0x4002d77c 0x00000000 0x4081ddd4 0x4081a680 0x00000000
17:06:11.231 -> 4085eef0: 0x00000000 0x4081a000 0x40818000 0x4200009e 0x00000000 0x00000000 0x40818000 0x420001fe
17:06:11.231 -> 4085ef10: 0x00000000 0x00000000 0x00000000 0x4201627a 0x00000000 0x00000000 0x00000000 0x4080eb90
17:06:11.231 -> 4085ef30: 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000
17:06:11.231 -> 4085ef50: 0x00000000 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5
17:06:11.264 -> 4085ef70: 0xbaad5678 0x00000168 0xabba1234 0x0000015c 0x4085edd0 0x00000621 0x40818718 0x40818718
17:06:11.264 -> 4085ef90: 0x4085ef80 0x40818710 0x00000018 0x00000000 0x00000000 0x4085ef80 0x00000000 0x00000001
17:06:11.264 -> 4085efb0: 0x4085cf70 0x706f6f6c 0x6b736154 0x00000000 0x00000000 0x4085ef60 0x00000004 0x00000000
17:06:11.264 -> 4085efd0: 0x00000001 0x00000000 0x00000000 0x00000000 0x00087b79 0x00000000 0x4081b07c 0x4081b0e4
17:06:11.297 -> 4085eff0: 0x4081b14c 0x00000000 0x00000000 0x00000001 0x00000000 0x00000000 0x00000000 0x4201ff38
17:06:11.297 -> 4085f010: 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000
17:06:11.297 -> 4085f030: 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000
17:06:11.297 -> 4085f050: 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000
17:06:11.331 -> 4085f070: 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000
17:06:11.331 -> 4085f090: 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000
17:06:11.331 -> 4085f0b0: 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000
17:06:11.331 -> 4085f0d0: 0x00000000 0x00000000 0x00000000 0xbaad5678 0x00000068 0xabba1234 0x0000005c 0x00000000
17:06:11.377 -> 4085f0f0: 0x4085f0ec 0x00000000 0x00000000 0x00000000 0x4085f104 0xffffffff 0x4085f104 0x4085f104
17:06:11.377 -> 
17:06:11.377 -> 
17:06:11.377 -> 
17:06:11.377 -> ELF file SHA256: e0cfe4d84
17:06:11.377 -> 
17:06:11.424 -> Rebooting...

I have tried keeping it as simple as just using NimBLEDevice::deinit() without the additional NimBLEScan cleanup calls but have experienced the same result.

justcallmekoko avatar Aug 01 '25 21:08 justcallmekoko

Any chance you can decode that backtrace?

h2zero avatar Aug 01 '25 22:08 h2zero

I don't have much experience doing that. I have only done it a few times and it was a long time ago.

justcallmekoko avatar Aug 01 '25 22:08 justcallmekoko

Honestly, your code to deinit isn't required as the call to NimBLEDevice::deinit(); will do the same thing anyway. Try that and let me know what happens.

h2zero avatar Aug 01 '25 23:08 h2zero

Yea that's what I tried first. My first attempt was the initialization function you see there followed by a simple NimBLEDevice::deinit() but it yields the same result

justcallmekoko avatar Aug 02 '25 01:08 justcallmekoko

Okay, I'll look into it, thanks!

h2zero avatar Aug 02 '25 02:08 h2zero

I am having this same issue, and it is related to the nimble_port_deinit() command on the NimBLEDevice::deinit(bool clearAll);

https://github.com/h2zero/NimBLE-Arduino/blob/5aaade087896d0da77d4e2ff821eaa2a637c3de8/src/NimBLEDevice.cpp#L1014

~probably an issue with the ESP-IDF 5.5 release used to build the Arduino-Esp32 framework, that is bound to commit cc3ac5416b46e6e9363dae357378c03b4975cfdb of https://github.com/espressif/esp-nimble/~

I am using the latest version, 2.3.4, the Stack trace related to the code above is this:

  Largest Free Block:   180212 B ( 176.0 KB)
------------------------------------------
Flash Info:
------------------------------------------
  Chip Size         :  8388608 B (8 MB)
  Block Size        :    65536 B (  64.0 KB)
  Sector Size       :     4096 B (   4.0 KB)
  Page Size         :      256 B (   0.2 KB)
  Bus Mode          : QIO
------------------------------------------
Partitions Info:
------------------------------------------
                nvs : addr: 0x00009000, size:    24.0 KB, type: DATA, subtype: NVS
               app0 : addr: 0x00010000, size:  4992.0 KB, type:  APP, subtype: OTA_0
             spiffs : addr: 0x004F0000, size:  3072.0 KB, type: DATA, subtype: SPIFFS
           coredump : addr: 0x007F0000, size:    64.0 KB, type: DATA, subtype: COREDUMP
------------------------------------------
Software Info:
------------------------------------------
  Compile Date/Time : Aug 11 2025 17:36:08
  ESP-IDF Version   : v5.5-1-gb66b5448e0
  Arduino Version   : 3.3.0
------------------------------------------
Board Info:
------------------------------------------
  Arduino Board     : Espressif ESP32-C5-DevKitC-1 8MB no PSRAM
  Arduino Variant   : pinouts
  Core Debug Level  : 5
  Arduino Runs Core : 0
  Arduino Events on : 0
  Arduino USB Mode  : 1
  CDC On Boot       : 1
============ Before Setup End ============
[  4779][I][esp32-hal-periman.c:141] perimanSetPinBus(): Pin 13 already has type USB_DM (38) with bus 0x4081fc00
  #0  0x4081fc00 in ?? at C:/Users/bmorcelli/.platformio/packages/framework-arduinoespressif32/cores/esp32/HWCDC.cpp:611

[  4779][I][esp32-hal-periman.c:141] perimanSetPinBus(): Pin 14 already has type USB_DP (39) with bus 0x4081fc00
  #0  0x4081fc00 in ?? at C:/Users/bmorcelli/.platformio/packages/framework-arduinoespressif32/cores/esp32/HWCDC.cpp:611

I NimBLEDevice: BLE Host Task Started
I NimBLEDevice: NimBle host synced.
Init BLE complete
Deinitializing BLE...
Clearing results...
Unbinding callbacks...

assert failed: multi_heap_free multi_heap_poisoning.c:279 (head != NULL)
Core  0 register dump:
MEPC    : 0x40800e40  RA      : 0x4080ee88  SP      : 0x4085ec30  GP      : 0x40819484  
  #0  0x40800e40 in panic_abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp_system/panic.c:483

TP      : 0x4085ee80  T0      : 0x37363534  T1      : 0x7271706f  T2      : 0x33323130  
S0/FP   : 0x00000001  S1      : 0x4085eda8  A0      : 0x4085ec94  A1      : 0x4081d0b9  
A2      : 0x00000001  A3      : 0x00000029  A4      : 0x00000001  A5      : 0x40828000  
A6      : 0x0000000c  A7      : 0x76757473  S2      : 0x0000007f  S3      : 0x4085ec88  
S4      : 0x4085ec88  S5      : 0x4085ec94  S6      : 0x00000000  S7      : 0x00000000  
S8      : 0x00000000  S9      : 0x00000000  S10     : 0x00000000  S11     : 0x00000000  
T3      : 0x6e6d6c6b  T4      : 0x6a696867  T5      : 0x66656463  T6      : 0x62613938  
MSTATUS : 0x00001881  MTVEC   : 0x40800003  MCAUSE  : 0x00000002  MTVAL   : 0x00000000  
MHARTID : 0x00000000  

Stack memory:
4085ec30: 0x00000000 0x00000000 0x4213e298 0x408144d8 0x30303030 0xba000000 0x4085ed40 0x4081d0b8
  #0  0x408144d8 in esp_libc_include_assert_impl at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/newlib/src/assert.c:96
  #1  0x4081d0b8 in __global_pointer$ at ??:?

4085ec50: 0xffffffff 0x00000046 0x40828000 0x00393732 0x4212cd54 0x4081d0a0 0x4213e298 0x4081d53c
  #0  0x4081d0a0 in __global_pointer$ at ??:?
  #1  0x4081d53c in __global_pointer$ at ??:?

4085ec70: 0x4212cdb6 0x4081d0b0 0x4085ec5c 0x4081d0b4 0x4212cd90 0x4081d0b8 0x00000000 0x00000000
  #0  0x4081d0b0 in __global_pointer$ at ??:?
  #1  0x4081d0b4 in __global_pointer$ at ??:?
  #2  0x4081d0b8 in __global_pointer$ at ??:?

4085ec90: 0x00000000 0x65737361 0x66207472 0x656c6961 0x6d203a64 0x69746c75 0x6165685f 0x72665f70
4085ecb0: 0x6d206565 0x69746c75 0x6165685f 0x6f705f70 0x6e6f7369 0x2e676e69 0x37323a63 0x68282039
4085ecd0: 0x20646165 0x4e203d21 0x294c4c55 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000
4085ecf0: 0x40828000 0x00000001 0x4082fd70 0x4001db2c 0x4085ee80 0x40020d0c 0x4207075a 0x00000200
  #0  0x4207075a in npl_freertos_callout_deinit at ??:?

4085ed10: 0x408302b0 0x00000000 0x0000001f 0x4085ed34 0x00000001 0xf7000002 0x00000000 0x40814120
  #0  0x40814120 in verify_allocated_region at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/heap/multi_heap_poisoning.c:102

4085ed30: 0xfff00000 0x4082fd7c 0xbaad5678 0xba000000 0x40828000 0xba000000 0xfff00000 0x00000000
4085ed50: 0x00000000 0x00000000 0x00000000 0x747a959f 0x40860000 0x00000000 0x00000000 0x00000000
4085ed70: 0x40828000 0x4082fd78 0x40828260 0x40813eee 0x40828000 0x40828000 0x4082fd5c 0x4208b172
  #0  0x40813eee in multi_heap_free at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/heap/multi_heap_poisoning.c:286      
  #1  0x4208b172 in r_ble_ll_mem_generic_data_deinit at ??:?

4085ed90: 0x40828000 0x40828000 0x4082809c 0x4208ff50 0x40828000 0x00000000 0x206d0000 0x4207add4
  #0  0x4208ff50 in r_ble_ll_scan_env_deinit at ??:?
  #1  0x4207add4 in r_ble_ll_env_deinit at ??:?

4085edb0: 0x40828000 0x00000000 0x206d0000 0x420976c4 0x40828000 0x00000000 0x4081c000 0x42070414
  #0  0x420976c4 in r_ble_controller_deinit at ??:?
  #1  0x4081c000 in __global_pointer$ at ??:?
  #2  0x42070414 in esp_bt_controller_deinit at ??:?

4085edd0: 0x40828000 0x00000000 0x00000000 0x42020670 0x40828000 0x00000000 0x00000000 0x4200cd3a
  #0  0x42020670 in nimble_port_deinit at .pio/libdeps/esp32-c5/NimBLE-Arduino/src/nimble/porting/nimble/src/nimble_port.c:231
  #1  0x4200cd3a in NimBLEDevice::deinit(bool) at .pio/libdeps/esp32-c5/NimBLE-Arduino/src/NimBLEDevice.cpp:1024

4085edf0: 0x00000000 0x00000000 0x00000000 0x00000000 0x00000014 0x40828000 0x40828000 0x00000000
4085ee10: 0x00000000 0x40828000 0x40820000 0x42022242 0x00000014 0x00000000 0x40820000 0x4202236a
  #0  0x42022242 in deinitBLE() at src/main.cpp:544
  #1  0x4202236a in setup() at src/main.cpp:567

4085ee30: 0x00000000 0x00000000 0x40828000 0x4202b6a4 0x00000000 0x00000000 0x00000000 0x40810222
  #0  0x4202b6a4 in loopTask(void*) at C:/Users/bmorcelli/.platformio/packages/framework-arduinoespressif32/cores/esp32/main.cpp:75
  #1  0x40810222 in vPortTaskWrapper at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/FreeRTOS-Kernel/portable/riscv/port.c:258

4085ee50: 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000
4085ee70: 0x00000000 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5
4085ee90: 0xbaad5678 0x00000168 0xabba1234 0x0000015c 0x4085ecf0 0x00001805 0x4082072c 0x4082072c
4085eeb0: 0x4085eea0 0x40820724 0x00000018 0x4085f228 0x4085f228 0x4085eea0 0x00000000 0x00000001
4085eed0: 0x4085ce90 0x706f6f6c 0x6b736154 0x00000000 0x00000000 0x4085ee80 0x00000005 0x00000000
4085eef0: 0x00000001 0x00000000 0x00000000 0x00000000 0x00098813 0x00000000 0x4082891c 0x40828984
4085ef10: 0x408289ec 0x00000000 0x00000000 0x00000001 0x00000000 0x00000000 0x4085f3a8 0x420361d8
  #0  0x420361d8 in esp_cleanup_r at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/newlib/src/newlib_init.c:42

4085ef30: 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000
4085ef50: 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000
4085ef70: 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000
4085ef90: 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000
4085efb0: 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000
4085efd0: 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000
4085eff0: 0x00000000 0x00000000 0x00000000 0xbaad5678 0x00000068 0xabba1234 0x0000005c 0x00000000
4085f010: 0x4085f00c 0x00000000 0x00000000 0x00000000 0x4085f024 0xffffffff 0x4085f024 0x4085f024



ELF file SHA256: f609e5db1

Rebooting...

bmorcelli avatar Aug 12 '25 12:08 bmorcelli

same here 😥

7h30th3r0n3 avatar Aug 12 '25 20:08 7h30th3r0n3

I'm experiencing the same issue on ESP32-C6 with 2.3.4, instant crash on deinit() and reboot. It happens with either value of the argument.

pkoryzna avatar Aug 22 '25 14:08 pkoryzna

This appears to be an issue upstream, the backtrace indicates that when esp_bt_controller_deinit is called is when the crash occurs, which is not a function in this library. I do not have a C5 to test with I'll check with a C6.

h2zero avatar Aug 25 '25 16:08 h2zero

I have confirmed the issue on an esp32c6 and also confirmed that the cause is an upstream bug as it also happens with the BLE library included in the Arduino core:

#include <BLEDevice.h>

void setup() {
    BLEDevice::init("");
    delay(1000);
    BLEDevice::deinit();
}

void loop() {}

Not sure if I can workaround this or not.

h2zero avatar Aug 26 '25 19:08 h2zero

So could potentially have to wait for an upstream fix in the esp32 core before this gets resolved?

justcallmekoko avatar Sep 02 '25 16:09 justcallmekoko

The only workaround for now is to comment out the call to esp_bt_controller_deinit, the controller won't deinitailize so the resources will still be consumed but at least the rest of the stack will be.

h2zero avatar Sep 02 '25 16:09 h2zero

Hi @h2zero

I am facing above same issue in ESP32 H2 board. When call NimBLEDevice::deinit(); crash the ESP and reboot it NimBLE lib version 2.3.6 ESP board version : 3.3.0

keenravi-hub avatar Nov 28 '25 12:11 keenravi-hub

@keenravi-hub Unfortunately this is not fixable within this library as it is an upstream bug and will need to wait for the Arduino core to be updated.

h2zero avatar Dec 03 '25 19:12 h2zero