mirror of
https://github.com/storytold/soundcraft.git
synced 2026-10-26 03:26:49 -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
715 B
Rust
15 lines
715 B
Rust
//! At process exit the host runs the module exit of every module it loaded, after releasing the
|
|
//! factory and before the module's statics are torn down (`harness = false`: the process exit is
|
|
//! what is under test). The fixture aborts the process if that order breaks, much as real plugins
|
|
//! crash: HALion Sonic segfaulted in its static destructors after a plain plugin scan.
|
|
|
|
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");
|
|
drop(p);
|
|
println!("module_exit: ok");
|
|
}
|