From b22fbcd77da8c9724ed08228b89cfea53afdd5b6 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 10 Dec 2019 15:11:10 -0600 Subject: [PATCH 1/3] supervisor: external_flash: don't call m_malloc_maybe when it's bad --- supervisor/shared/external_flash/external_flash.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/supervisor/shared/external_flash/external_flash.c b/supervisor/shared/external_flash/external_flash.c index 99df553e19..e7d86240b4 100644 --- a/supervisor/shared/external_flash/external_flash.c +++ b/supervisor/shared/external_flash/external_flash.c @@ -324,6 +324,10 @@ static bool allocate_ram_cache(void) { return true; } + if (MP_STATE_MEM(gc_pool_start) == 0) { + return false; + } + MP_STATE_VM(flash_ram_cache) = m_malloc_maybe(blocks_per_sector * pages_per_block * sizeof(uint32_t), false); if (MP_STATE_VM(flash_ram_cache) == NULL) { return false; From f4a5c17b5e79cf9bd02be248620d445065891a25 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 10 Dec 2019 17:05:37 -0600 Subject: [PATCH 2/3] supervisor: external_flash: don't call m_free when it's bad It's extremely dubious that we have these handles that we think are to GC'd memory at a time when the gc pool may not be initialized. Hopefully, they WERE valid GC memory and are undisturbed by the teardown of the interpreter that can lead to this state. In this case, don't try to m_free them, the memory will become free when the GC heap is reinitialized. Closes: #2338 (together with previous commit) --- supervisor/shared/external_flash/external_flash.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/supervisor/shared/external_flash/external_flash.c b/supervisor/shared/external_flash/external_flash.c index e7d86240b4..9d38c07d89 100644 --- a/supervisor/shared/external_flash/external_flash.c +++ b/supervisor/shared/external_flash/external_flash.c @@ -371,7 +371,7 @@ static void release_ram_cache(void) { if (supervisor_cache != NULL) { free_memory(supervisor_cache); supervisor_cache = NULL; - } else { + } else if (MP_STATE_MEM(gc_pool_start)) { m_free(MP_STATE_VM(flash_ram_cache)); } MP_STATE_VM(flash_ram_cache) = NULL; @@ -419,7 +419,7 @@ static bool flush_ram_cache(bool keep_cache) { write_flash(current_sector + (i * pages_per_block + j) * SPI_FLASH_PAGE_SIZE, MP_STATE_VM(flash_ram_cache)[i * pages_per_block + j], SPI_FLASH_PAGE_SIZE); - if (!keep_cache && supervisor_cache == NULL) { + if (!keep_cache && supervisor_cache == NULL && MP_STATE_MEM(gc_pool_start)) { m_free(MP_STATE_VM(flash_ram_cache)[i * pages_per_block + j]); } } From 6305d489475f0eb91b0fba59fd93fc72191a28eb Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 10 Dec 2019 17:05:47 -0600 Subject: [PATCH 3/3] gc_free: give a better error when freeing outside of VM --- py/gc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/py/gc.c b/py/gc.c index a8a5fde125..5e631f5ed8 100755 --- a/py/gc.c +++ b/py/gc.c @@ -667,6 +667,9 @@ void gc_free(void *ptr) { if (ptr == NULL) { GC_EXIT(); } else { + if (MP_STATE_MEM(gc_pool_start) == 0) { + reset_into_safe_mode(GC_ALLOC_OUTSIDE_VM); + } // get the GC block number corresponding to this pointer assert(VERIFY_PTR(ptr)); size_t block = BLOCK_FROM_PTR(ptr);