G0.3: watchdog giu 15s khi attach-in-flight (SHM flag) + RAII guard trong attach job (fix kill nham khi GUI mo)
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -49,4 +49,10 @@ struct SharedAudioBufferIPC {
|
|||||||
char arg2[1024]; // LOAD: UTF-8 path
|
char arg2[1024]; // LOAD: UTF-8 path
|
||||||
} controlQueue[8];
|
} controlQueue[8];
|
||||||
volatile uint32_t controlQueueCount;
|
volatile uint32_t controlQueueCount;
|
||||||
|
|
||||||
|
// G0.3: set by the bridge while an openGUI attach job is in flight
|
||||||
|
// (reload/attachView on a ChannelWorker). The Tauri watchdog reads this
|
||||||
|
// to extend its stall deadline — a long Nexus attach must not look like
|
||||||
|
// a dead bridge. Append-only field: existing offsets stay stable.
|
||||||
|
volatile uint32_t attachInFlight;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -940,6 +940,14 @@ int main(int argc, char* argv[]) {
|
|||||||
// a window on a worker whose pump is idle during jobs hangs
|
// a window on a worker whose pump is idle during jobs hangs
|
||||||
// view->attached() (gui_probe: two_workers_close TIMEOUT). The attach
|
// view->attached() (gui_probe: two_workers_close TIMEOUT). The attach
|
||||||
// job runs on the channel worker (COM STA apartment stays alive).
|
// job runs on the channel worker (COM STA apartment stays alive).
|
||||||
|
// G0.3: while an attach job is in flight, tell the Tauri watchdog via
|
||||||
|
// SHM so a long Nexus reload/attach (can exceed 3s) is not mistaken
|
||||||
|
// for a dead bridge and killed. RAII -> cleared on every exit path.
|
||||||
|
struct AttachInFlightGuard {
|
||||||
|
SharedAudioBufferIPC* ipc;
|
||||||
|
explicit AttachInFlightGuard(SharedAudioBufferIPC* p) : ipc(p) { if (ipc) ipc->attachInFlight = 1; }
|
||||||
|
~AttachInFlightGuard() { if (ipc) ipc->attachInFlight = 0; }
|
||||||
|
};
|
||||||
auto handleOpenGui = [&](uint32_t guiCh, uintptr_t arg1, const std::string& pluginId) {
|
auto handleOpenGui = [&](uint32_t guiCh, uintptr_t arg1, const std::string& pluginId) {
|
||||||
if (!instruments.get(guiCh)) {
|
if (!instruments.get(guiCh)) {
|
||||||
std::cerr << "[NativeBridge] GUI deferred ch=" << guiCh
|
std::cerr << "[NativeBridge] GUI deferred ch=" << guiCh
|
||||||
@@ -1029,7 +1037,8 @@ int main(int argc, char* argv[]) {
|
|||||||
instruments.setReloading(guiCh, true);
|
instruments.setReloading(guiCh, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
workers[guiCh]->post([&instruments, guiCh, hwnd, arg2 = pluginId]() {
|
workers[guiCh]->post([&instruments, shmIPC, guiCh, hwnd, arg2 = pluginId]() {
|
||||||
|
AttachInFlightGuard _aifGuard{shmIPC};
|
||||||
if (!instruments.get(guiCh)) {
|
if (!instruments.get(guiCh)) {
|
||||||
std::cerr << "[NativeBridge] GUI attach FAILED hwnd=" << hwnd
|
std::cerr << "[NativeBridge] GUI attach FAILED hwnd=" << hwnd
|
||||||
<< " plugin=" << arg2 << " ch=" << guiCh << " (no instrument loaded)" << std::endl;
|
<< " plugin=" << arg2 << " ch=" << guiCh << " (no instrument loaded)" << std::endl;
|
||||||
|
|||||||
+16
-1
@@ -383,6 +383,21 @@ pub fn run() {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
// G0.3: an openGUI attach job (reload/attachView on the
|
||||||
|
// bridge worker) can legitimately outlast the 3s stall
|
||||||
|
// deadline if it blocks the audio loop's message pump —
|
||||||
|
// do not kill the bridge for that. Real stalls are still
|
||||||
|
// caught: attach never takes > 15s; a dead bridge leaves
|
||||||
|
// the flag stuck and is restarted after the longer wait.
|
||||||
|
let attach_deadline = guard
|
||||||
|
.as_ref()
|
||||||
|
.map(|s| s.attach_in_flight())
|
||||||
|
.unwrap_or(false);
|
||||||
|
let stall_deadline = if attach_deadline {
|
||||||
|
std::time::Duration::from_secs(15)
|
||||||
|
} else {
|
||||||
|
std::time::Duration::from_secs(3)
|
||||||
|
};
|
||||||
if advanced == Some(true) {
|
if advanced == Some(true) {
|
||||||
last_change = std::time::Instant::now();
|
last_change = std::time::Instant::now();
|
||||||
down_emitted = false;
|
down_emitted = false;
|
||||||
@@ -394,7 +409,7 @@ pub fn run() {
|
|||||||
"bridge-audio",
|
"bridge-audio",
|
||||||
AudioFrame { l: l.to_vec(), r: r.to_vec() },
|
AudioFrame { l: l.to_vec(), r: r.to_vec() },
|
||||||
);
|
);
|
||||||
} else if last_change.elapsed() >= std::time::Duration::from_secs(3) && !down_emitted {
|
} else if last_change.elapsed() >= stall_deadline && !down_emitted {
|
||||||
// Check lai truoc khi respawn — Destroyed co the vua set flag.
|
// Check lai truoc khi respawn — Destroyed co the vua set flag.
|
||||||
if SHUTTING_DOWN.load(Ordering::Relaxed) {
|
if SHUTTING_DOWN.load(Ordering::Relaxed) {
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -59,6 +59,10 @@ pub struct SharedAudioBufferIPC {
|
|||||||
pub midi_queue_count: u32,
|
pub midi_queue_count: u32,
|
||||||
pub control_queue: [ControlEventIPC; CONTROL_QUEUE_CAP],
|
pub control_queue: [ControlEventIPC; CONTROL_QUEUE_CAP],
|
||||||
pub control_queue_count: u32,
|
pub control_queue_count: u32,
|
||||||
|
// G0.3: bridge sets this while an openGUI attach job is in flight.
|
||||||
|
// Append-only field — offsets of control_queue (2836) and
|
||||||
|
// control_queue_count (11156) are unchanged.
|
||||||
|
pub attach_in_flight: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Shm {
|
pub struct Shm {
|
||||||
@@ -158,6 +162,10 @@ impl Shm {
|
|||||||
pub fn block_timestamp(&self) -> u64 {
|
pub fn block_timestamp(&self) -> u64 {
|
||||||
self.ipc().block_timestamp
|
self.ipc().block_timestamp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn attach_in_flight(&self) -> bool {
|
||||||
|
self.ipc().attach_in_flight != 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for Shm {
|
impl Drop for Shm {
|
||||||
@@ -180,6 +188,6 @@ mod tests {
|
|||||||
// native_bridge/tests/shm_selfcheck.cpp asserts the same sizes.
|
// native_bridge/tests/shm_selfcheck.cpp asserts the same sizes.
|
||||||
assert_eq!(std::mem::size_of::<MidiEventIPC>(), 12);
|
assert_eq!(std::mem::size_of::<MidiEventIPC>(), 12);
|
||||||
assert_eq!(std::mem::size_of::<ControlEventIPC>(), 1040);
|
assert_eq!(std::mem::size_of::<ControlEventIPC>(), 1040);
|
||||||
assert_eq!(std::mem::size_of::<SharedAudioBufferIPC>(), 11160);
|
assert_eq!(std::mem::size_of::<SharedAudioBufferIPC>(), 11164);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user