fix(bridge): one editor at a time + guard reload race

- Close other channels' editor windows before attaching a new one (Option B)
- needsReload()/setReloading() guard: skip processAudioBlock during
  terminate+reload teardown to avoid UAF/hang when reopening GUI
- Wait for editor registry cleanup (5s timeout) before creating window
This commit is contained in:
2026-08-13 15:32:35 +07:00
parent c3eb0c9d16
commit 05e4244cc8
7 changed files with 349 additions and 4 deletions
+7 -1
View File
@@ -170,7 +170,8 @@ Vst3Instrument::Vst3Instrument()
maxBlockSize_(256),
loaded_(false),
guiAttached_(false),
hasAttachedOnce_(false) {}
hasAttachedOnce_(false),
reloading_(false) {}
Vst3Instrument::~Vst3Instrument() {
#ifdef HAVE_VST3SDK
@@ -598,6 +599,11 @@ void Vst3Instrument::processAudioBlock(float* outputL, float* outputR, uint32_t
#ifndef HAVE_VST3SDK
return;
#else
// GUI reopen rebuilds the instance on the worker thread; while the
// teardown runs, the audio loop must not touch state_ (flag toggled under
// InstrumentEngineManager::mu_ by setReloading — renderAll holds the same
// mutex during processAudioBlock, so the check is race-free).
if (reloading_) return;
auto* s = static_cast<Vst3HostState*>(state_);
if (!s || !s->component || numSamples == 0) return;
FUnknownPtr<IAudioProcessor> processor(s->component);