fix: stale-reload watchdog — force-unmute channel stuck in reloading >20s (60s if close/attach in flight) (V9)
This commit is contained in:
Binary file not shown.
@@ -75,7 +75,7 @@ static void disable_ime_contexts(HWND w) {
|
||||
|
||||
// G1.3: bo pump gate cu (g_juceOwnerTids / g_ownerTid /
|
||||
// is_teardown_window): teardown (close/LOAD job) va message pump cung chay tren
|
||||
// 1 thread (UiThread) — job chay thi pump dung, job xong thi editor window da
|
||||
// 1 thread (UiThread) � job chay thi pump dung, job xong thi editor window da
|
||||
// destroy nen USER32 tu huy message toi window chet. Khong con "2 thread trong
|
||||
// 1 DLL" khi teardown (multi-worker cu).
|
||||
|
||||
@@ -295,7 +295,7 @@ public:
|
||||
for (int pumped = 0; pumped < 128; ++pumped) {
|
||||
if (!PeekMessageW(&msg, nullptr, 0, 0, PM_REMOVE)) break;
|
||||
hadMessages = true;
|
||||
// G1.3: bo pump gate cu — teardown (close/LOAD job)
|
||||
// G1.3: bo pump gate cu � teardown (close/LOAD job)
|
||||
// va pump cung 1 thread (UiThread): job chay thi pump dung;
|
||||
// het job thi editor window da destroy -> message chet bi
|
||||
// USER32 huy tu dong. Khong can drop theo close_in_flight.
|
||||
@@ -423,7 +423,7 @@ static bool close_in_flight(uint32_t ch) {
|
||||
|
||||
|
||||
|
||||
// G1.3: 1 UiThread — editor windows tao trong attach job (UiThread), destroy
|
||||
// G1.3: 1 UiThread � editor windows tao trong attach job (UiThread), destroy
|
||||
// chi goi tu UiThread job (close_editor_now / LOAD) -> ownerTid luon == current
|
||||
// tid -> destroy truc tiep. Neu owner khac thread (khong con xay ra) -> bo
|
||||
// (leak > crash): cross-thread DestroyWindow khong an toan.
|
||||
@@ -1352,6 +1352,42 @@ int main(int argc, char* argv[]) {
|
||||
}
|
||||
|
||||
|
||||
// V8 bug 5 (stale-reload watchdog): a close/attach job can hang
|
||||
// inside createInstance (Nexus, observed) — reloading_ stays true
|
||||
// forever, the channel and its same-plugin siblings stay muted,
|
||||
// heartbeat keeps ticking so the Rust watchdog never respawns us:
|
||||
// permanent silence with no log. Scan once per second; a reload
|
||||
// older than 20s with no close/attach job in flight, or older than
|
||||
// 60s regardless, is stale — force-clear so the audio loop processes
|
||||
// the instance again. Risk (2 threads in one DLL) is bounded: SEH
|
||||
// SafeProcessChannel re-mutes on crash; a hard DLL deadlock stalls
|
||||
// writeIndex and Rust respawns the bridge (which recovers sound —
|
||||
// observed: restart fixed muted channels).
|
||||
{
|
||||
static bool reloadWasSet[16] = { false };
|
||||
static std::chrono::steady_clock::time_point reloadSeen[16];
|
||||
static auto lastScan = std::chrono::steady_clock::now();
|
||||
auto nowScan = std::chrono::steady_clock::now();
|
||||
if (std::chrono::duration_cast<std::chrono::milliseconds>(nowScan - lastScan).count() >= 1000) {
|
||||
lastScan = nowScan;
|
||||
for (uint32_t ch = 0; ch < 16; ++ch) {
|
||||
bool rl = instruments.isReloading(ch);
|
||||
if (!rl) { reloadWasSet[ch] = false; continue; }
|
||||
if (!reloadWasSet[ch]) { reloadWasSet[ch] = true; reloadSeen[ch] = nowScan; continue; }
|
||||
double sec = std::chrono::duration<double>(nowScan - reloadSeen[ch]).count();
|
||||
bool jobInFlight = shmIPC->attachInFlight != 0 || close_in_flight(ch);
|
||||
if (sec > 60.0 || (sec > 20.0 && !jobInFlight)) {
|
||||
std::cerr << "[NativeBridge] STALE-RELOAD watchdog ch=" << ch
|
||||
<< " reloading " << (int)sec << "s (attachInFlight="
|
||||
<< shmIPC->attachInFlight << " closeInFlight="
|
||||
<< close_in_flight(ch) << ") — force unmute" << std::endl;
|
||||
instruments.setReloading(ch, false);
|
||||
reloadWasSet[ch] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// B. Snapshot queued MIDI events (bounded copy, queue reset immediately)
|
||||
uint32_t nEvents = shmIPC->midiQueueCount > 64 ? 64 : shmIPC->midiQueueCount;
|
||||
SharedAudioBufferIPC::MidiEventIPC evts[64];
|
||||
|
||||
Reference in New Issue
Block a user