background_callback: Add gc collect callback

A background callback must never outlive its related object.  By
collecting the head of the linked list of background tasks, this will
not happen.

One hypothetical case where this could happen is if an MP3Decoder is
deleted while its callback to fill its buffer is scheduled.
This commit is contained in:
Jeff Epler 2020-07-17 08:36:26 -05:00
parent 81105cb9ef
commit a18a392109
3 changed files with 13 additions and 0 deletions

2
main.c
View File

@ -493,6 +493,8 @@ void gc_collect(void) {
// have lost their references in the VM even though they are mounted.
gc_collect_root((void**)&MP_STATE_VM(vfs_mount_table), sizeof(mp_vfs_mount_t) / sizeof(mp_uint_t));
background_callback_gc_collect();
#if CIRCUITPY_DISPLAYIO
displayio_gc_collect();
#endif

View File

@ -79,4 +79,9 @@ void background_callback_reset(void);
void background_callback_begin_critical_section(void);
void background_callback_end_critical_section(void);
/*
* Background callbacks may stop objects from being collected
*/
void background_callback_gc_collect(void);
#endif

View File

@ -24,6 +24,7 @@
* THE SOFTWARE.
*/
#include "py/gc.h"
#include "py/mpconfig.h"
#include "supervisor/background_callback.h"
#include "supervisor/shared/tick.h"
@ -105,3 +106,8 @@ void background_callback_reset() {
in_background_callback = false;
CALLBACK_CRITICAL_END;
}
void background_callback_gc_collect(void) {
background_callback_t *cb = (background_callback_t*)callback_head;
gc_collect_ptr(cb);
}