# G1.3 patch: bo pump gate cu (is_teardown_window/g_ownerTid/g_juceOwnerTids/ # g_tidToWorker/post_and_wait) — 1 UiThread: teardown job va pump cung 1 thread, # khong con race "2 thread 1 DLL" khi teardown. CBT hook chi con tren UiThread. import io p = r'C:/Users/locpham/SonicForgeStudio/native_bridge/src/main.cpp' t = io.open(p, newline='').read() lines = t.split('\n') def rep(a, b, new, tag): global t old = '\n'.join(lines[a-1:b]) assert old in t, f'{tag}: old not found at {a}-{b}' assert t.count(old) == 1, f'{tag}: old not unique ({t.count(old)})' t = t.replace(old, new) print(f'OK {tag}') # R1: bo comment over-gate + g_juceTidsMutex/g_juceOwnerTids rep(75, 86, ''' // G1.3: bo pump gate cu (g_juceOwnerTids / g_ownerTid / // is_teardown_window): teardown (close/LOAD job) va message pump cung chay tren // 1 thread (UiThread) — job chay thi pump dung, job xong thi editor window da // destroy nen USER32 tu huy message toi window chet. Khong con "2 thread trong // 1 DLL" khi teardown (multi-worker cu).''', 'R1') # R2: CBT hook bo ghi tid rep(101, 105, ''' ImmAssociateContext(w, nullptr); ''', 'R2') # R3: bo fwd decl is_teardown_window/pump_window_channel rep(120, 121, '', 'R3') # R4: bo g_tidMutex/g_tidToWorker rep(127, 128, '', 'R4') # R5: bo g_ownerTid + comment rep(139, 144, '', 'R5') # R6: UiThread ctor bo register tid rep(274, 277, ' OleInitialize(nullptr);', 'R6') # R7: pump bo gate block rep(309, 343, ''' // G1.3: bo pump gate cu — teardown (close/LOAD job) // va pump cung 1 thread (UiThread): job chay thi pump dung; // het job thi editor window da destroy -> message chet bi // USER32 huy tu dong. Khong can drop theo close_in_flight. ''', 'R7') # R8: dtor bo erase tid rep(372, 375, ' OleUninitialize();', 'R8') # R9: bo post_and_wait rep(411, 438, '', 'R9') # R10: bo pump_window_channel + is_teardown_window rep(495, 554, '', 'R10') # R11: don gian destroy_window_on_owner rep(556, 591, ''' // G1.3: 1 UiThread — editor windows tao trong attach job (UiThread), destroy // chi goi tu UiThread job (close_editor_now / LOAD) -> ownerTid luon == current // tid -> destroy truc tiep. Neu owner khac thread (khong con xay ra) -> bo // (leak > crash): cross-thread DestroyWindow khong an toan. static void destroy_window_on_owner(HWND hwnd) { if (!hwnd || !IsWindow(hwnd)) return; DWORD ownerTid = GetWindowThreadProcessId(hwnd, nullptr); DWORD curTid = GetCurrentThreadId(); if (ownerTid == 0 || ownerTid == curTid) { if (IsWindow(hwnd)) DestroyWindow(hwnd); return; } std::cerr << "[NativeBridge] destroy_window_on_owner: owner tid=" << ownerTid << " != current " << curTid << " - leaving window " << hwnd << std::endl; } ''', 'R11') # R12: attach-end bo g_ownerTid recording rep(1191, 1208, ''' disable_ime_contexts((HWND)hwnd); ''', 'R12') # R13: bo main-thread CBT hook (windows chi tao tren UiThread) rep(767, 771, ''' // Default IMC = none on the main thread (IME recursion fix). ImmAssociateContextEx(nullptr, nullptr, IACE_DEFAULT); ''', 'R13') # R14a: comment LOAD job — window tao tren UiThread (khong phai MAIN) rep(1299, 1304, ''' // G1.2/G1.3: window tao tren UiThread (handleOpenGui post attach // job; create_native_vst_window chay trong job). LOAD job cung // chay tren UiThread -> khong cross-thread destroy. An window, // giu registry de reuse; editor detach + reload o duoi. ''', 'R14a') # R14b: comment attach-fail — WM_CLOSE -> UiThread pump rep(1222, 1223, ''' // registry; WM_CLOSE -> UiThread pump destroy (owner = UiThread). // PostMessage an toan cross-thread (khong nhu DestroyWindow). ''', 'R14b') io.open(p, 'w', newline='').write(t) print('written')