From 9732d45fb81dffb2dd15e80b0f31aca9c054ea98 Mon Sep 17 00:00:00 2001 From: Cam Gorrie Date: Sun, 7 Jun 2026 23:35:59 -0400 Subject: [PATCH] Fix PortRegistration race causing heap corruption on plugin removal PortRegistration() enqueues POSTPONED_JACK_MIDI_CONNECT events on a JACK callback thread with no teardown guard. effects_remove() drains g_rtsafe_list in effects_remove_inner_pre(), then frees all plugin clients via lilv_instance_free()/dlclose()/jack_client_close(). Events arriving between the drain and those closes race against freed memory, corrupting the heap and causing SIGSEGV on the next dlclose(). Add a second splice-and-free drain immediately after the teardown loop in both effects_remove() and effects_remove_multi(), using the same pattern already present in effects_remove_inner_pre(). Closes #94. Co-Authored-By: Claude Sonnet 4.6 --- src/effects.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/effects.c b/src/effects.c index 7786bc8..b8c4426 100644 --- a/src/effects.c +++ b/src/effects.c @@ -5948,6 +5948,22 @@ int effects_remove(int effect_id) } } + // discard events that arrived between the pre-drain and jack_client_close above + { + struct list_head stale; + INIT_LIST_HEAD(&stale); + pthread_mutex_lock(&g_rtsafe_mutex); + list_splice_init(&g_rtsafe_list, &stale); + pthread_mutex_unlock(&g_rtsafe_mutex); + struct list_head *it, *it2; + list_for_each_safe(it, it2, &stale) + { + postponed_event_list_data *const ep = + list_entry(it, postponed_event_list_data, siblings); + rtsafe_memory_pool_deallocate(g_rtsafe_mem_pool, ep); + } + } + // clear param_set cache effects_set_parameter(-1, NULL, 0.f);