Files

4.9 KiB

Nexus GUI crash 0xc000041d (USER32) — debug state (WIP)

Thời điểm lưu: 2026-08-14, đang chuyển sang máy Linux để tiếp tục.

Hiện tượng

daw_vst_bridge.exe crash 0xc000041d khi mở GUI editor VSTi Nexus (C:\Program Files\Common Files\VST3\Nexus.vst3) rồi chọn instrument khác. Chạy từ install/.

Kết quả đã có

  • Probe gui_probe.exe variant bridge_exact11 PASS (RESULT(bridge_exact11): done=1 attached_ok=1, log: openGUI: attached=0 = kResultOk), kể cả khi stdout redirect ra file.
  • NHƯNG bridge thật HANG tại view->attached() (log dừng tại isPlatformTypeSupported=0, không in attached=), kể cả SF_ONCE_PROBEWIN=1. Watchdog tick vẫn chạy = đang trong attached().

Đã loại trừ (session 2026-08-14)

  • g_engine hypothesis DISPROVEN: g_engine (main.cpp L545) KHÔNG được dùng trong path SF_ONCE (chỉ dùng ở closeGUI/main-loop). Job SF_ONCE chỉ gọi instruments.setReloading(y,true) → Vst3Instrument::setReloading (chỉ set bool) + reloadForGUI() (hasAttachedOnce_=false lần đầu → no-op return true).
  • Diff ChannelWorker vs PumpWorker: giống hệt (chỉ khác tên biến + destructor + comment).
  • Diff exact11 vs SF_ONCE: giống hệt về ngữ nghĩa — chỉ khác sampleRate/block, setEditorOpenPredicate (cả hai false), SHM driver thật vs tự tạo (đã loại bằng SF_ONCE_SHM).
  • stdout redirect ra file: probe vẫn PASS.
  • Binary up-to-date (build 22:09 = main.cpp 22:09).
  • CMakeLists: bridge và gui_probe compile CÙNG sources, CÙNG defines (HAVE_VST3SDK=1), cùng libs — không khác.

Stack main thread (stackscan.py v7/v8)

  • Main thread chờ vô hạn trong ntdll (R9=0x7ffffffffffffffc timeout ~infinite) qua KERNELBASE+22cd8 gọi từ Nexus attached().
  • 3 thread Nexus riêng chờ ntdll+164034; 1 thread (21232) là message pump (win32u+20a4).
  • Export resolve thất bại (offset nội bộ không tên): ntdll+5fc6e→hàm tại 0x5fa90, ntdll+3e732→0x3dc60, KERNELBASE+22cd8→hàm tại 0x22ca0.

Bước tiếp theo

  1. waitscan.py (chạy dở khi lưu): dump RIP mọi thread + NtQueryObject loại/tên handle trong Rcx (wait object) — xem main thread và 3 thread Nexus có CÙNG chờ 1 object (deadlock nội bộ Nexus) hay không. Chạy: python waitscan.py (cần bridge đang hang).
  2. Nếu waitscan không rõ: disasm KERNELBASE+22ca0 / ntdll+5fa90 xác định hàm chờ (WaitForSingleObjectEx/WaitForMultipleObjectsEx/AlertableWait), hoặc NtQuerySystemInformation wait-chain.
  3. Khi tìm được trigger: REVERT toàn bộ TEST patch (watchdog, direct attach, no audio, DefWindowProcA, warm-up, pre-window, autogui, exact11, once, once_shm, probewin) — giữ fix chính thức. Đặc biệt:
    • wc.lpfnWndProc = DefWindowProcA; // TEST ISOLATION
    • bỏ WS_VISIBLE ở create_native_vst_window
    • khôi phục VstWindowProc + WS_VISIBLE khi hết test.
  4. Verify app thật từ install/ (kill SonicForge/daw_vst trước; check %APPDATA%\SonicForgeDAW\logs\bridge.log + spawn.log, không "bridge stalled 3s"). Deploy exe 5 vị trí: install/, src-tauri/binaries/ (2 tên), src-tauri/target/{debug,release}/.

Cách chạy (Windows)

  • Build: cd native_bridge && cmake --build build --config Release --target daw_vst_bridge --parallel (nhớ taskkill //F //IM daw_vst_bridge.exe trước, LNK1104 nếu zombie).
  • Probe: ./build/Release/gui_probe.exe "C:\Program Files\Common Files\VST3\Nexus.vst3" <variant> <secs>; exit 127 dù PASS; watchdog tự kill sau secs+10s.
  • Driver: python driver_once.py [GATE=VAL...] (chờ "SF_ONCE attach=" 90s + "GUI attached" 30s; attach=0 = THÀNH CÔNG).

Scripts trong thư mục này

  • waitscan.py — dump RIP + wait object mọi thread (đang dở, bước 1 tiếp theo).
  • stackscan.py / stackwalk.py / stack_sample*.py — stack dump.
  • driver_once.py / driver_verify.py / driver_autogui.py / driver_narrow.py — chạy bridge với gate, chờ kết quả.
  • Patch scripts (workspace tmp-7d619832): patch_once.py, patch_once_shm.py, patch_exact11_bridge.py, patch_gates.py, patch_autogui.py, ... áp bằng python lên native_bridge/src/main.cpp (CRLF! ghi io.open(encoding='utf-8', newline='\r\n')).

Learnings kỹ thuật (Windows ctypes)

  • GetModuleHandleW/windll trả pointer → PHẢI set .restype = ctypes.c_void_p (mặc định c_int → truncate 32-bit → access violation).
  • Mọi API nhận pointer/handle → set argtypes (GetThreadContext, OpenThread, DuplicateHandle...).
  • ctypes.wintypes KHÔNG có DWORD64 — dùng ctypes.c_uint64.
  • CONTEXT x64: SegCs..SegSs là WORD; struct đầy đủ 0x4d0 bytes; GetThreadContext ghi full buffer → dùng raw buffer 0x4d0 + struct.unpack_from offset cố định (rip@0xF8, rsp@0x98, rcx@0x80, rdx@0x88, r8@0xB8, r9@0xC0, ContextFlags@0x30).
  • EnumProcessModulesEx: cb = bytes/8 trên x64; module handle có thể NULL → skip.