From e5893d06928baf7932d25332bc4c28f05d94cce9 Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Sun, 20 Aug 2023 14:50:46 -0500 Subject: [PATCH] Fix reference counting for threaded abstract types. Was very borked. The sweep phase should drop references to unused abstracts but wasn't, resulting in each collection decrementing the count by one until 0 was hit, even if other threads maintained a reference. --- src/core/abstract.c | 2 +- src/core/gc.c | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/core/abstract.c b/src/core/abstract.c index 84879801..b8b21ebf 100644 --- a/src/core/abstract.c +++ b/src/core/abstract.c @@ -182,7 +182,7 @@ void janet_os_mutex_lock(JanetOSMutex *mutex) { void janet_os_mutex_unlock(JanetOSMutex *mutex) { int ret = pthread_mutex_unlock((pthread_mutex_t *) mutex); - if (ret) janet_panic("cannot release lock"); + if (ret) janet_panicf("cannot release lock: %s", strerror(ret)); } void janet_os_rwlock_init(JanetOSRWLock *rwlock) { diff --git a/src/core/gc.c b/src/core/gc.c index f0ecdd9a..9e7ecba5 100644 --- a/src/core/gc.c +++ b/src/core/gc.c @@ -364,20 +364,22 @@ void janet_sweep() { /* If not visited... */ if (!janet_truthy(items[i].value)) { void *abst = janet_unwrap_abstract(items[i].key); + if (0 == janet_abstract_decref(abst)) { /* Run finalizer */ JanetAbstractHead *head = janet_abstract_head(abst); if (head->type->gc) { janet_assert(!head->type->gc(head->data, head->size), "finalizer failed"); } - /* Mark as tombstone in place */ - items[i].key = janet_wrap_nil(); - items[i].value = janet_wrap_false(); - janet_vm.threaded_abstracts.deleted++; - janet_vm.threaded_abstracts.count--; /* Free memory */ janet_free(janet_abstract_head(abst)); } + + /* Mark as tombstone in place */ + items[i].key = janet_wrap_nil(); + items[i].value = janet_wrap_false(); + janet_vm.threaded_abstracts.deleted++; + janet_vm.threaded_abstracts.count--; } /* Reset for next sweep */