Skip to content

Bugfix: memory leak caused by variables not being deleted in end() #237

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
May 30, 2022

Conversation

alranel
Copy link
Contributor

@alranel alranel commented May 12, 2022

This pull request addresses the issue described in #192 caused by variables initialized in begin() not being deleted in end(). This leads to hangs and crashes reported also in other issues.

@buffcode
Copy link

This will crash the board on Arduino Uno Wifi Rev2. At first I thought it worked because the memory was freed, but it was only because the board resets and starts all over (observable by logging something in setup).

It does not reset in the current master, but instead will eat memory

Minimal reproduction sketch
#include <MemoryUsage.h>
#include <ArduinoBLE.h>

void setup() {
  Serial.begin(9600);
  while (!Serial);

  Serial.println("===================");
  Serial.println("Setup, you should only see this once");
  Serial.println("===================");
}

void loop() {
  // begin initialization
  if (!BLE.begin()) {
    Serial.println("starting Bluetooth® Low Energy module failed!");

    while (1);
  }

  // start scanning for peripheral
  Serial.println("starting Bluetooth® Low Energy scan");
  Serial.print("Free memory: ");
  Serial.println(mu_freeRam());
  BLE.scan();
  BLE.stopScan();

  // crashes here
  Serial.println("BLE.end");
  BLE.end();
}
Output with this PR:
09:00:58.238 -> ===================
09:00:58.272 -> Setup, you should only see this once
09:00:58.306 -> ===================
09:00:59.228 -> starting Bluetooth® Low Energy scan
09:00:59.262 -> Free memory: 4587
09:00:59.296 -> BLE.end
09:00:59.296 -> ⸮==================
09:00:59.330 -> Setup, you should only see this once
09:00:59.364 -> ===================
09:01:00.286 -> starting Bluetooth® Low Energy scan
09:01:00.320 -> Free memory: 4587
09:01:00.320 -> BLE.end
09:01:00.353 -> ===================
09:01:00.387 -> Setup, you should only see this once
09:01:00.422 -> ===================
Output in `master`:
09:02:10.105 -> ===================
09:02:10.105 -> Setup, you should only see this once
09:02:10.171 -> ===================
09:02:11.060 -> starting Bluetooth® Low Energy scan
09:02:11.129 -> Free memory: 4587
09:02:11.129 -> BLE.end
09:02:12.052 -> starting Bluetooth® Low Energy scan
09:02:12.086 -> Free memory: 4271
09:02:12.120 -> BLE.end
09:02:13.042 -> starting Bluetooth® Low Energy scan
09:02:13.076 -> Free memory: 3955
09:02:13.110 -> BLE.end
09:02:14.031 -> starting Bluetooth® Low Energy scan
09:02:14.066 -> Free memory: 3639
09:02:14.100 -> BLE.end
09:02:15.021 -> starting Bluetooth® Low Energy scan
09:02:15.055 -> Free memory: 3323
09:02:15.055 -> BLE.end

@facchinm
Copy link
Contributor

Hi @buffcode ,
I retested this branch (with a couple of patches on top) with a slight modification of your code on all the boards currently supported by the library.
Everything looks ok, no leaks and no reboots; here's the code I used if you want to try replicate in your setup

#ifdef __MBED__
#include <mbed.h>
#include <mbed_mem_trace.h>
#else
#include <MemoryFree.h>
#endif
#include <ArduinoBLE.h>

#ifdef __MBED__
REDIRECT_STDOUT_TO(Serial)

void print_memory_info() {
    // allocate enough room for every thread's stack statistics
    int cnt = osThreadGetCount();
    mbed_stats_stack_t *stats = (mbed_stats_stack_t*) malloc(cnt * sizeof(mbed_stats_stack_t));
 
    cnt = mbed_stats_stack_get_each(stats, cnt);
    for (int i = 0; i < cnt; i++) {
        printf("Thread: 0x%lX, Stack size: %lu / %lu\r\n", stats[i].thread_id, stats[i].max_size, stats[i].reserved_size);
    }
    free(stats);
 
    // Grab the heap statistics
    mbed_stats_heap_t heap_stats;
    mbed_stats_heap_get(&heap_stats);
    printf("Heap size: %lu / %lu bytes\r\n", heap_stats.current_size, heap_stats.reserved_size);
}
#else

void print_memory_info() {
  Serial.println(freeMemory());
}

#endif

void setup() {
  Serial.begin(9600);
  while (!Serial);

  Serial.println("===================");
  Serial.println("Setup, you should only see this once");
  Serial.println("===================");
}

void loop() {

  print_memory_info();

  // begin initialization
  if (!BLE.begin()) {
    Serial.println("starting Bluetooth® Low Energy module failed!");

    while (1);
  }

  // start scanning for peripheral
  Serial.println("starting Bluetooth® Low Energy scan");
  BLE.scan();
  BLE.stopScan();

  Serial.println("BLE.end");
  BLE.end();
}

@facchinm facchinm merged commit 3003f12 into arduino-libraries:master May 30, 2022
@ricozinn
Copy link

ricozinn commented May 30, 2022

Hi @buffcode I tried release 1.3.0 and your test code above on the Artemis Redboard (uses Apollo3 chipset) and got the same crash as before. I'm running this release of the Sparkfun Apollo3 board: https://github.com/sparkfun/Arduino_Apollo3/releases/tag/v2.2.1

A couple things about my test...

  1. I had to comment out this line REDIRECT_STDOUT_TO(Serial) since it wouldn't compile for me
  2. printing out the memory info always just printed: 11:02:32.209 -> Heap size: 0 / 0 bytes. There was no printout for any running threads.
  3. It crashed at the same place as before (after 25 cycles of BLE.begin() followed by BLE.end())

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
criticality: high Of high impact topic: code Related to content of the project itself type: imperfection Perceived defect in any part of project
Projects
None yet
Development

Successfully merging this pull request may close these issues.

ArduinoBLE crashes when BLE.begin BLE.end is called multiple times (possible solution included)
5 participants