fix(plugin): stop the editor aborting the host on Windows - #284
Merged
Conversation
Loading the VST3 in REAPER on Windows killed the DAW the moment the editor
opened, with exception 0xc0000409 and Rustortion.vst3 as the faulting module.
That code is `__fastfail(FATAL_APP_EXIT)` -- Rust's `abort()`. nih-plug's log
had the cause:
panicked at 'called `Option::unwrap()` on a `None` value':
iced_baseview/src/conversion.rs:781
The Win32 arm of `convert_raw_window_handle` tested `hinstance.is_null()` and
then unwrapped `NonZeroIsize::new(hinstance)` inside the `.then()` closure --
which runs precisely when the pointer *is* null. baseview fills in only `hwnd`
and leaves `hinstance` null on every window, so this fired on every editor open;
the panic crossed the extern "C" wrapper boundary, became a non-unwinding panic,
and aborted the host. Linux takes the Xlib arm, which is why neither CI nor
local dev ever saw it.
Fixed upstream in the fork (OpenSauce/iced_baseview@f76ba2f1), which recovers the
HINSTANCE from the window via `GetWindowLongPtrW(GWLP_HINSTANCE)` rather than
passing the null through -- wgpu's Vulkan backend refuses a surface without one.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
With the Windows abort out of the way the editor renders, but flickers while it is open. `IcedBaseviewSettings::default()` leaves `always_redraw` off, so iced redraws only when it decides it has something new to show. baseview cannot request a redraw when the window's visibility changes, so between the two the window can end up presenting a swapchain buffer that nothing ever drew into -- stale on Windows, blank on a reopened editor. Upstream's own doc comment describes the default as the thing to work around, and `nih_plug_iced` hard-codes the opposite (`nih_plug_iced/src/editor.rs:104`). Cost is a redraw per baseview window update while the editor is open, which is what every other iced-based plugin editor already pays. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
…ring" This reverts commit b0b4b5d. It did not fix the flicker, and it broke the dropdowns: `always_redraw` forces `needs_update` true on every frame (iced_baseview application.rs:424), which tears down and rebuilds the whole `UserInterface` continuously -- and a `pick_list` dropdown is an overlay that has to survive across frames to stay open and take a click. The flicker turned out to follow the graphics backend, not the redraw rate: forcing `WGPU_BACKEND=gl` removes it while the default DX12 path shows it. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
The dep pointed at a bare `rev` on a topic branch (`f76ba2f1`, on `fix/win32-hinstance`), which is not a released state and says nothing about what it contains. The fork now has a `v0.1.0` tag containing that fix — PR #1 merged, plus a metadata commit — so pin to the tag instead. Resolves to a0c8040d, verified to contain f76ba2f1. CLAUDE.md called this an "unpinned git dep", which was already wrong and is now doubly so; corrected to name the tag and say that moving it means cutting a release on the fork first.
Contributor
There was a problem hiding this comment.
Pull request overview
This PR addresses a Windows-only crash where opening the VST3 editor could abort the host (panic crossing an extern "C" boundary) by updating the iced_baseview fork dependency to a released tag that includes the Win32 HINSTANCE recovery fix.
Changes:
- Pin
iced_baseviewinrustortion-pluginto thev0.1.0git tag (instead of a barerev). - Update
Cargo.lockto reflect the tagged commit and resulting dependency resolution. - Correct
CLAUDE.mdto document the dependency as tag-pinned and clarify the upgrade procedure.
Reviewed changes
Copilot reviewed 2 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| rustortion-plugin/Cargo.toml | Switch iced_baseview dependency from a specific rev to the v0.1.0 tag. |
| Cargo.lock | Lockfile updates reflecting the tagged iced_baseview commit and transitive dependency resolution changes. |
| CLAUDE.md | Documentation update to accurately describe iced_baseview as pinned to v0.1.0 and note release/tag expectations. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Loading the VST3 in REAPER on Windows killed the DAW the moment the editor opened, with exception 0xc0000409 and Rustortion.vst3 as the faulting module.
That code is
__fastfail(FATAL_APP_EXIT)-- Rust'sabort(). nih-plug's log had the cause:The Win32 arm of
convert_raw_window_handletestedhinstance.is_null()and then unwrappedNonZeroIsize::new(hinstance)inside the.then()closure -- which runs precisely when the pointer is null. baseview fills in onlyhwndand leaveshinstancenull on every window, so this fired on every editor open; the panic crossed the extern "C" wrapper boundary, became a non-unwinding panic, and aborted the host. Linux takes the Xlib arm, which is why neither CI nor local dev ever saw it.Fixed upstream in the fork (OpenSauce/iced_baseview@f76ba2f1), which recovers the HINSTANCE from the window via
GetWindowLongPtrW(GWLP_HINSTANCE)rather than passing the null through -- wgpu's Vulkan backend refuses a surface without one.Dependency pin
The fork dep now points at the
v0.1.0tag rather than a barerevon a topic branch:v0.1.0resolves toa0c8040dand contains the fix (f76ba2f1merged via PR #1, plus a repository-metadata commit) -- verified withgit merge-base --is-ancestor. A barerevon a topic branch is not a released state and says nothing about what it holds; a tag does.CLAUDE.mddescribed this as an "unpinned git dep", which was already inaccurate and is now doubly so, so it is corrected in the same commit to name the tag and note that moving it means cutting a release on the fork first.Testing
cargo check -p rustortion-pluginbuilds clean against the tag. The Windows crash itself still needs verifying on Windows -- neither CI nor Linux dev exercises the Win32 arm, which is how the bug survived in the first place.