mirror of
https://github.com/storytold/soundcraft.git
synced 2026-10-26 11:36:51 -06:00
vst3-host ran each module's entry (bundleEntry / InitDll / ModuleEntry) when it loaded a .vst3 and cached the module for the life of the process, but never ran the matching exit or released the cached factory. At exit() the module's static destructors then ran on a module that was never shut down. Steinberg's HALion Sonic segfaults there, so every process that had scanned VST3 plugins crashed on exit: the app on quit, soundcraft-cli, and the engine, mix and vst3-host unit tests. At process exit each module now has its factory released and its exit run, newest first, on the thread that ran its entry: Native Instruments' Massive X crashes in bundleExit on any other thread. Loads asked for off the main thread go to a long-lived module thread, which also runs their exits. Modules with a live instance or a leaked editor view are left alone, later loads are refused, and plugin code stays mapped. The exit handler is registered with atexit after each new module, so it runs ahead of that module's static destructors; it uses OS thread ids because std::thread::current() panics in exit handlers. A module whose entry ran but that then fails to load now gets its exit too. The fixture plugin now checks the module lifecycle and aborts the process when it is broken. Three harness = false tests cover the exit after use, a live instance at exit, and a load from a short-lived thread. Fixes #16 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
15 lines
730 B
Rust
15 lines
730 B
Rust
//! A module with a plugin instance still alive at process exit keeps running: its module exit
|
|
//! would pull the module out from under that instance (`harness = false`, see `module_exit.rs`).
|
|
//! The fixture aborts the process if its module exit runs while any of its objects are alive.
|
|
|
|
mod common;
|
|
|
|
fn main() {
|
|
let dir = common::fixture_dir();
|
|
let gain = soundcraft_vst3_host::scan_paths(&[dir.to_path_buf()]).into_iter().find(|d| d.name == "Fixture Gain").expect("fixture").id;
|
|
let p = soundcraft_vst3_host::instantiate_plugin(&gain).expect("instantiate");
|
|
// Still alive at exit, like a plugin held by a mixer that is never torn down.
|
|
std::mem::forget(p);
|
|
println!("module_exit_live_instance: ok");
|
|
}
|