diff options
| author | Jeff Epler <jepler@gmail.com> | 2020-07-17 14:55:46 -0500 |
|---|---|---|
| committer | Jeff Epler <jepler@gmail.com> | 2020-07-17 14:55:46 -0500 |
| commit | 98eef79faaa36adbdd0b074c712aad5df7ef37a0 (patch) | |
| tree | 71df1bacd12748bf71788c59095033763a59db62 | |
| parent | 6912d31560a617a134fcadbfdc1800a259f5e465 (diff) | |
background_callback_gc_collect: We must traverse the whole list
| -rw-r--r-- | supervisor/shared/background_callback.c | 19 |
1 files changed, 18 insertions, 1 deletions
diff --git a/supervisor/shared/background_callback.c b/supervisor/shared/background_callback.c index 1be3cae2b..d10579c4f 100644 --- a/supervisor/shared/background_callback.c +++ b/supervisor/shared/background_callback.c @@ -108,6 +108,23 @@ void background_callback_reset() { } void background_callback_gc_collect(void) { + // We don't enter the callback critical section here. We rely on + // gc_collect_ptr _NOT_ entering background callbacks, so it is not + // possible for the list to be cleared. + // + // However, it is possible for the list to be extended. We make the + // minor assumption that no newly added callback is for a + // collectable object. That is, we only plug the hole where an + // object becomes collectable AFTER it is added but before the + // callback is run, not the hole where an object was ALREADY + // collectable but adds a background task for itself. + // + // It's necessary to traverse the whole list here, as the callbacks + // themselves can be in non-gc memory, and some of the cb->data + // objects themselves might be in non-gc memory. background_callback_t *cb = (background_callback_t*)callback_head; - gc_collect_ptr(cb); + while(cb) { + gc_collect_ptr(cb->data); + cb = cb->next; + } } |
