Sometime ago (last year) I noticed that several projects would freeze up when switching presets. This could happen anywhere, within HISE itself, VST/AU or standalone. Not being a crash in the traditional sense (ui locks up/beach-balling occurs), there was no crash report, so today I turned to AI to get to the bottom of it. The common thread seems to be slider packs and tables, both of which feature heavily in all the affected projects (perhaps the reason this hasn't come up before, is the number of packs & tables involved? perhaps if you only have one or two it's less of a problem).
Below is the ai's (long winded) description of the problem, and our eventual solution:
Summary
In the users project, preset switching could freeze standalone/AU. The freeze correlated with presets containing ScriptSliderPack / ScriptTable data blobs. Root cause appears to be complex-data restore running off the message thread and colliding with UI-side updates/rebuild.
Environment
- macOS (Apple Silicon)
- JUCE v6.1.3 (as printed by app)
- HISE dev build: a21269a
- Repro in standalone, HISE and plugin hosts
Observed behaviour
- Intermittent freeze during preset loading.
- Same preset might load in one session and freeze in another.
- Assertion seen at MiscToolClasses.h:1219 (multiple writer threads) in debug builds.
Key stacks (relevant frames)
- Sample-loading thread:
UserPresetHandler::loadUserPresetInternal
Content::restoreAllControlsFromPreset
ComplexDataScriptComponent::restoreFromValueTree
SliderPackData::fromBase64 -> swapBuffer
assert in SimpleReadWriteLock::ScopedWriteLock (MiscToolClasses.h:1219)
- Message thread simultaneously:
SliderPack::timerCallback -> SliderPack::rebuildSliders
Root cause hypothesis
ComplexDataScriptComponent::restoreFromValueTree applies fromBase64String directly, which can execute off-message-thread during preset load. That can race with message-thread UI/component activity around the same complex data object.
Minimal fix that worked
In ScriptingApiContent.cpp, inside ComplexDataScriptComponent::restoreFromValueTree:
if on message thread: apply immediately
otherwise: MessageManager::callAsync(...) and apply there
So the complex data apply is always done on the message thread.
Patch
hise-complexdata-message-thread.patch
Validation
With this narrow patch:
- pack/table preset recall works again
- rapid preset switching no longer freezes in tested project.
Notes
This issue was hard to isolate because normal warnings (Identifier, audio/HAL logs, etc.) are noisy and non-causal; the decisive signal was the lock assertion stack involving complex data restore + sliderpack UI activity.
Sometime ago (last year) I noticed that several projects would freeze up when switching presets. This could happen anywhere, within HISE itself, VST/AU or standalone. Not being a crash in the traditional sense (ui locks up/beach-balling occurs), there was no crash report, so today I turned to AI to get to the bottom of it. The common thread seems to be slider packs and tables, both of which feature heavily in all the affected projects (perhaps the reason this hasn't come up before, is the number of packs & tables involved? perhaps if you only have one or two it's less of a problem).
Below is the ai's (long winded) description of the problem, and our eventual solution:
Summary
In the users project, preset switching could freeze standalone/AU. The freeze correlated with presets containing ScriptSliderPack / ScriptTable data blobs. Root cause appears to be complex-data restore running off the message thread and colliding with UI-side updates/rebuild.
Environment
Observed behaviour
Key stacks (relevant frames)
UserPresetHandler::loadUserPresetInternal
Content::restoreAllControlsFromPreset
ComplexDataScriptComponent::restoreFromValueTree
SliderPackData::fromBase64 -> swapBuffer
assert in SimpleReadWriteLock::ScopedWriteLock (MiscToolClasses.h:1219)
SliderPack::timerCallback -> SliderPack::rebuildSliders
Root cause hypothesis
ComplexDataScriptComponent::restoreFromValueTree applies fromBase64String directly, which can execute off-message-thread during preset load. That can race with message-thread UI/component activity around the same complex data object.
Minimal fix that worked
In ScriptingApiContent.cpp, inside ComplexDataScriptComponent::restoreFromValueTree:
if on message thread: apply immediately
otherwise: MessageManager::callAsync(...) and apply there
So the complex data apply is always done on the message thread.
Patch
hise-complexdata-message-thread.patch
Validation
With this narrow patch:
Notes
This issue was hard to isolate because normal warnings (Identifier, audio/HAL logs, etc.) are noisy and non-causal; the decisive signal was the lock assertion stack involving complex data restore + sliderpack UI activity.