fix slow leak in link-establishing thread-resume

Using `(thread-resume t1 t2)` would not prevent a GC of t1, but it
would create an intermediate record to make the link from t1 to t2,
and that intermediate record would leak due to a missing level of
indirection in a table-cleanup traveral. The leak not only accumulated
memory, it also caused ever slower traversals of the table in an
attempt to clean up.

(Since the leak is small and the leaking object is not directly
accessible, I don't have a good idea on how to test this repair
automatically, but see the program in the PR.)

Closes PR 15099.
This commit is contained in:
Matthew Flatt 2015-06-22 16:43:42 +08:00
parent 82218f33bd
commit ca57adcf2d

View File

@ -5779,15 +5779,17 @@ static void add_transitive_resume(Scheme_Thread *promote_to, Scheme_Thread *p)
promote_to->transitive_resumes = (Scheme_Object *)ht;
} else {
/* Purge ht entries for threads that are now dead: */
Scheme_Hash_Table *gone= NULL;
Scheme_Hash_Table *gone = NULL;
Scheme_Object *b;
int i;
ht = (Scheme_Hash_Table *)promote_to->transitive_resumes;
for (i = ht->size; i--; ) {
if (ht->vals[i]) {
if (!SCHEME_PTR_VAL(ht->keys[i])
|| (SAME_TYPE(SCHEME_TYPE(ht->keys[i]), scheme_weak_box_type)
&& !SCHEME_WEAK_BOX_VAL(ht->vals[i]))) {
b = SCHEME_PTR_VAL(ht->keys[i]);
if (!b
|| (SAME_TYPE(SCHEME_TYPE(b), scheme_weak_box_type)
&& !SCHEME_WEAK_BOX_VAL(b))) {
/* This one is dead */
if (!gone)
gone = scheme_make_hash_table(SCHEME_hash_ptr);