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:
@@ -27,6 +27,7 @@
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// --- platform helpers -------------------------------------------------------
|
||||
static bool parent_alive(uint32_t pid) {
|
||||
@@ -366,6 +367,48 @@ int main(int argc, char* argv[]) {
|
||||
<< " plugin=" << arg2 << " ch=" << guiCh << std::endl;
|
||||
void* hwnd = (void*)(uintptr_t)arg1;
|
||||
#ifdef _WIN32
|
||||
// Option B: chi 1 editor VST mo tai 1 thoi diem toan
|
||||
// bridge. Instance thu 2 cua CUNG plugin (Nexus) attach
|
||||
// view o apartment/worker khac -> treo (bridge.log: ch=2
|
||||
// ket o attached() khi ch=1 con mo) / crash (gui_probe
|
||||
// bridge_two). Dong editor cua channel khac TRUOC khi
|
||||
// attach: WM_CLOSE -> worker channel do destroy window ->
|
||||
// WM_DESTROY -> closeGUI() -> view->removed() tren dung
|
||||
// thread so huu (gui_probe two_instances_close: OK).
|
||||
{
|
||||
std::vector<uint32_t> others;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(g_guiMutex);
|
||||
for (const auto& kv : g_guiWindows)
|
||||
if (kv.first != guiCh) others.push_back(kv.first);
|
||||
}
|
||||
for (uint32_t y : others) {
|
||||
HWND yHwnd = nullptr;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(g_guiMutex);
|
||||
auto it = g_guiWindows.find(y);
|
||||
if (it != g_guiWindows.end()) yHwnd = (HWND)it->second;
|
||||
}
|
||||
if (!yHwnd || !IsWindow(yHwnd)) continue;
|
||||
PostMessage(yHwnd, WM_CLOSE, 0, 0);
|
||||
std::cerr << "[dbg] openGUI: closing editor ch=" << y
|
||||
<< " before attach ch=" << guiCh << std::endl;
|
||||
// Cho worker channel y xu ly WM_CLOSE -> destroy ->
|
||||
// WM_DESTROY (xoa registry). Timeout 5s tranh
|
||||
// worker ket (load lau / plugin treo).
|
||||
bool closed = false;
|
||||
for (int i = 0; i < 500; ++i) {
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(g_guiMutex);
|
||||
if (g_guiWindows.find(y) == g_guiWindows.end()) { closed = true; break; }
|
||||
}
|
||||
Sleep(10);
|
||||
}
|
||||
if (!closed)
|
||||
std::cerr << "[dbg] openGUI: editor ch=" << y
|
||||
<< " not closed in 5s, proceeding" << std::endl;
|
||||
}
|
||||
}
|
||||
if (arg1 == 0) {
|
||||
HWND existingHwnd = nullptr;
|
||||
{
|
||||
@@ -400,7 +443,17 @@ int main(int argc, char* argv[]) {
|
||||
(void)0;
|
||||
#endif
|
||||
if (auto* inst = instruments.get(guiCh)) {
|
||||
if (inst->openGUI(hwnd))
|
||||
// Reopen sau khi dong: openGUI() rebuild lai plugin
|
||||
// instance (reload = terminate + loadPlugin) trong
|
||||
// khi audio loop co the dang processAudioBlock tren
|
||||
// CUNG object -> UAF/hang. Chan bang flag reloading_
|
||||
// (set/clear duoi engine mutex; renderAll giu mutex
|
||||
// khi process nen check luon nhat quan).
|
||||
bool guard = inst->needsReload();
|
||||
if (guard) instruments.setReloading(guiCh, true);
|
||||
bool ok = inst->openGUI(hwnd);
|
||||
if (guard) instruments.setReloading(guiCh, false);
|
||||
if (ok)
|
||||
std::cout << "[NativeBridge] GUI attached hwnd=" << hwnd
|
||||
<< " plugin=" << arg2 << " ch=" << guiCh << std::endl;
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user