Crash in ScriptDownloadObject destructor at plugin teardown (EXC_BAD_ACCESS 0x58) — 4.9.2, macOS
-
anyone has experience with this?
We have reason to believe that this could be fixed only inside HISE. Looking to confirm this with a HISE specialist
thank youReport:
Crash on destroying ScriptDownloadObject — HISE 4.9.2, macOS arm64
EXC_BAD_ACCESS (SIGSEGV), KERN_INVALID_ADDRESS at 0x0000000000000058Destroying a ScriptDownloadObject crashes inside its own base-class destructor chain. It happens wherever the destruction occurs — on the server thread during a run, or on the message thread at plugin teardown.
Roughly 25 reproductions across three builds. Symbolicated against the exact binaries that crashed.
The crash
Identical top four frames in every single report:juce::DynamicObject::~DynamicObject() + 104
hise::ApiClass::~ApiClass() + 192
hise::ScriptingObjects::ScriptDownloadObject::~ScriptDownloadObject() + 372
hise::ScriptingObjects::ScriptDownloadObject::~ScriptDownloadObject() + 12
The destructor body itself is trivial (ScriptingApiObjects.cpp:1172) and is not where it dies — +372 is inside the implicit base-class destruction that follows.Three call paths, same object
- Message thread, at plugin close — the common case:
hise::JavascriptThreadPool::~JavascriptThreadPool() + 64
hise::GlobalServer::~GlobalServer() + 12 / + 280
hise::GlobalServer::WebThread::~WebThread() + 176
→ ScriptDownloadObject::~ScriptDownloadObject() → crash
2. Server thread, mid-run:juce::threadEntryProc(void*) + 284
hise::GlobalServer::WebThread::run() + 5464
→ ScriptDownloadObject::~ScriptDownloadObject() → crash
WebThread::run() copies pendingDownloads into a local ReferenceCountedArray thisList each iteration. When that local goes out of scope holding the last reference, the object is destroyed on the web thread.- Download thread — the same fault seen from the other side:
juce::threadEntryProc(void*) + 284
juce::FallbackDownloadTask::run() + 100
hise::ScriptingObjects::ScriptDownloadObject::progress(DownloadTask*, int64, int64) + 260
juce::NamedValueSet::set(juce::Identifier const&, juce::var const&) + 44
KERN_INVALID_ADDRESS at 0x0 here. The object had already been destroyed and the still-running download task called progress() on it, writing into a NamedValueSet that no longer existed.So: destroy it while the task is live and the task writes into freed memory; destroy it later and the destructor itself dies.
Reproduction
HISE 4.9.2, macOS 15.5, Apple Silicon, Cubase 15, VST3
A plugin script that downloads a series of files via Server.downloadFile(), each subsequent download started from the previous one's completion callback
16 downloads, ~150 MB total, real network transfers
Crash on closing the plugin after the run completes
Notes on reproducing it:Real transfers are required. If the target files already exist and resumeInternal short-circuits to success, nothing crashes.
Frequency is high but not certain — roughly 15 crashes in 18 runs on the affected machine. It also occurred with only 4 downloads, so a long run is not needed.
Not observed on several other machines, which may point at timing, host, or network speed.
What we ruled out
Not the manifest or the URLs. Two different manifests, byte-identical addresses; a file that crashed one run downloaded cleanly the next.
Not a shutdown timeout. HISE_SCRIPT_SERVER_TIMEOUT is 10000 ms and the thread appears to stop cleanly.
Not fixable from HiseScript. Two attempts:
Removing all Server.cleanFinishedDownloads() calls from the run. This removed the server-thread crashes (8 of 9 → 1 of 8) but the objects then survived to teardown and crashed there instead.
Retaining a script-side reference to every download object, so HISE's ReferenceCountedArray would never be the last owner. No effect — and the stack shows why: GlobalServer is destroyed from JavascriptThreadPool::~JavascriptThreadPool(), so the script's own array is destroyed in the same operation. The refcount reaches zero regardless.
What it looks like from outside
The object's DynamicObject base appears already invalid at the point of destruction — consistent with a double release, or with the object being released after something it depends on has gone.