Files
feedBack-desktop/src/audio/addon/EditorWindows.h
T
OmikronApexandClaude Fable 5 ea8c6a9ccd fix(audio): address PR #107 review — close serializer gaps, editor lifetime races, dispatch failures
All 8 CodeRabbit findings verified against the code and fixed:

- ChainOps: macOS LoadVST routes its addProcessor through chainMutationMutex
  (macOS is a first-class platform; deadlock-safe — a worker holding the
  mutex never waits on the Node/main thread there). All four single-slot
  workers (LoadVST/NAM/IR/ReplaceIR) now bump chainGeneration so the
  executor's foreign-write detection sees direct loads, not just presets.
- Rebuild barrier (beginChainRebuild/endChainRebuild): LoadPreset and
  ClearChain arm it before editor teardown; OpenPluginEditor refuses to
  open while a teardown+clear/rebuild is pending (#56 window between
  closeAllPluginEditorWindows returning and the worker taking the mutex).
- EditorWindows: all slot/processor resolution in editor lambdas runs under
  a try_lock of chainMutationMutex (try_lock, never blocking — workers
  holding the mutex block-wait on the message thread). Sandbox promotion
  bumps chainGeneration. editorWindows map is now message-thread-only
  (duplicate-window check and close-erase moved into the queued lambdas).
  Null slot->processor recheck after a faulted promotion capture.
- closeAllPluginEditorWindows returns false on refused post / 15s timeout;
  ClearChain skips the clear and LoadPreset resolves {success:false}
  instead of freeing processors under a live editor.
- AddonContext: dispatchOnMessageThread reports refused-post/timeout;
  doShutdown leaves the message thread running when teardown didn't
  complete instead of unloading mid-destruction.
- RendererBus::push rejects NaN/Inf/non-positive rates and a step that
  underflows to zero; new testRejectsUnusableRates unit case.

Verified: addon builds clean, all 78 JS tests pass (storm, contracts,
executor, N-API fuzz), all 5 engine_units native tests pass.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 11:56:08 +02:00

32 lines
1.4 KiB
C++

#pragma once
// EditorWindows — in-process plugin editor windows + the open/close bindings
// and the Windows sandbox-promotion flow (TLC plan phase 7 / §3.4). Moved
// verbatim from NodeAddon.cpp. Owns the slotId→window map (message-thread
// only) and the teardown helpers every chain-clearing path must run BEFORE
// freeing slot processors (use-after-free; feedBack-desktop#56).
#include <napi.h>
namespace slopsmith::addon {
// Inline teardown: destroys every editor window. Caller MUST already be on
// the message thread (the window map holds JUCE GUI objects). doShutdown's
// UI teardown hook points here.
void destroyAllPluginEditorWindowsOnMessageThread();
// Tears down the in-process editor windows so they are destroyed before the
// caller frees the processors those editors point at. Safe from the Node
// thread (posts to the message thread and blocks, bounded) or the message
// thread itself (inline). Clearing an empty map is cheap.
// Returns false when teardown did NOT complete (post refused or the bounded
// wait timed out) — the caller must not free chain processors in that case
// (#56 use-after-free).
bool closeAllPluginEditorWindows();
// N-API bindings (registered by NodeAddon's export table).
Napi::Value OpenPluginEditor(const Napi::CallbackInfo& info);
Napi::Value ClosePluginEditor(const Napi::CallbackInfo& info);
} // namespace slopsmith::addon