G3.2+G3.3: classify hang/crash vs audio stall + SEH per-channel plugin crash isolation (mute channel)
This commit is contained in:
@@ -9,6 +9,8 @@
|
||||
#define FS_SYNTH (static_cast<fluid_synth_t*>(synth))
|
||||
#define FS_SETTINGS (static_cast<fluid_settings_t*>(settings))
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <cstring>
|
||||
@@ -206,8 +208,9 @@ bool InstrumentEngineManager::assign(uint32_t channel, InstrumentType type,
|
||||
types_[channel] = type;
|
||||
// Fresh instance is by construction not reloading — clear the channel
|
||||
// flag so real-time MIDI dispatch (which drops reloading channels)
|
||||
// flows to it again.
|
||||
// flows to it again. G3.3: a reload also clears the crash-mute.
|
||||
reloadingCh_[channel] = false;
|
||||
crashedCh_[channel] = false;
|
||||
}
|
||||
if (oldInst) {
|
||||
isBypassed_.store(true);
|
||||
@@ -300,11 +303,23 @@ bool InstrumentEngineManager::isReloading(uint32_t channel) const {
|
||||
return channel < 16 && reloadingCh_[channel];
|
||||
}
|
||||
|
||||
// Quiet = reloading (mid-rebuild) only. G1.4: bo mute-when-editor-open —
|
||||
// editor co the mo trong luc PLAY, audio loop van process() binh thuong.
|
||||
void InstrumentEngineManager::markCrashed(uint32_t channel) {
|
||||
std::lock_guard<std::mutex> lock(mu_);
|
||||
if (channel < 16) crashedCh_[channel] = true;
|
||||
}
|
||||
|
||||
bool InstrumentEngineManager::isCrashed(uint32_t channel) const {
|
||||
std::lock_guard<std::mutex> lock(mu_);
|
||||
return channel < 16 && crashedCh_[channel];
|
||||
}
|
||||
|
||||
// Quiet = reloading (mid-rebuild) OR crashed (G3.3). G1.4: bo
|
||||
// mute-when-editor-open — editor co the mo trong luc PLAY, audio loop van
|
||||
// process() binh thuong. G3.3: channel crash -> mute vi trang thai plugin
|
||||
// khong xac dinh sau fault; xu ly tiep se fault lai.
|
||||
// Called with mu_ held by the real-time dispatch.
|
||||
bool InstrumentEngineManager::channelQuiet(uint32_t ch) const {
|
||||
if (ch >= 16 || reloadingCh_[ch]) return true;
|
||||
if (ch >= 16 || reloadingCh_[ch] || crashedCh_[ch]) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -362,6 +377,20 @@ void InstrumentEngineManager::allNotesOff() {
|
||||
}
|
||||
}
|
||||
|
||||
// G3.3: SEH cannot live inside a function that needs C++ unwinding (C2712),
|
||||
// so per-channel process() runs in this helper. A plugin access violation
|
||||
// (0xC0000005) is caught here — the channel is muted instead of killing the
|
||||
// whole bridge process. /EHa (set in CMakeLists) allows mixing with the
|
||||
// outer C++ try/catch net in main.cpp.
|
||||
static bool SafeProcessChannel(INativeInstrument* inst, float* outL, float* outR, uint32_t n) {
|
||||
__try {
|
||||
inst->processAudioBlock(outL, outR, n);
|
||||
return true;
|
||||
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void InstrumentEngineManager::renderAll(float* outputL, float* outputR, uint32_t numSamples) {
|
||||
if (isBypassed_.load()) {
|
||||
std::memset(outputL, 0, numSamples * sizeof(float));
|
||||
@@ -377,10 +406,19 @@ void InstrumentEngineManager::renderAll(float* outputL, float* outputR, uint32_t
|
||||
scratchR_.resize(numSamples);
|
||||
}
|
||||
for (auto& [ch, inst] : channels_) {
|
||||
if (channelQuiet(ch)) continue; // editor open on this plugin DLL: do not process
|
||||
if (channelQuiet(ch)) continue; // editor open / crashed: do not process
|
||||
std::memset(scratchL_.data(), 0, numSamples * sizeof(float));
|
||||
std::memset(scratchR_.data(), 0, numSamples * sizeof(float));
|
||||
inst->processAudioBlock(scratchL_.data(), scratchR_.data(), numSamples);
|
||||
if (!SafeProcessChannel(inst.get(), scratchL_.data(), scratchR_.data(), numSamples)) {
|
||||
// G3.3: plugin fault — mute this channel only, keep the bridge up.
|
||||
if (!crashedCh_[ch]) {
|
||||
crashedCh_[ch] = true;
|
||||
std::cerr << "[NativeBridge] G3.3: channel " << ch
|
||||
<< " plugin crashed in processAudioBlock (SEH) — muted until reload"
|
||||
<< std::endl;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
for (uint32_t i = 0; i < numSamples; ++i) {
|
||||
outputL[i] += scratchL_[i];
|
||||
outputR[i] += scratchR_[i];
|
||||
|
||||
Reference in New Issue
Block a user