pm-grid: hardening - bound the USB-MIDI TX queue + defensive set-list guard
Audit for panic/brick risks (a panic = black screen on this device): - sx_send (live-sync broadcasts + 5s heartbeat) pushed to tx_q with no cap. If the editor disconnects without a BYE while sync_armed and nothing drains MIDI-IN, tx_q grows unbounded -> heap exhaustion -> brick. Now drops messages when tx_q > 256 (the heartbeat re-syncs when the host returns). Notes/clock were already capped. - build_setlists now drops empty set lists, so load()/next_track() can never hit a `% 0`. (parse guarantees >=1 lane; built-ins/parsed lists are non-empty, this is belt-and-suspenders.) Other unwrap()s are boot-time peripheral init; lanes[0]/items[0]/step[0] are all safe (parse substitutes beep:4 for empty programs; built-ins lead the list). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
dd27d553fe
commit
72dbb2ecd0
1 changed files with 7 additions and 0 deletions
|
|
@ -216,6 +216,7 @@ fn build_setlists(user: Vec<SetList>) -> Vec<SetList> {
|
|||
})
|
||||
.collect();
|
||||
v.extend(user);
|
||||
v.retain(|s| !s.items.is_empty()); // never keep an empty set list (would `% 0` in load/next)
|
||||
v
|
||||
}
|
||||
|
||||
|
|
@ -946,6 +947,12 @@ impl App {
|
|||
|
||||
/// Build `F0 7D <op> <text(ASCII-clamped)> F7`, packetize into 4-byte USB-MIDI events, queue them.
|
||||
fn sx_send(&mut self, op: u8, text: &str) {
|
||||
// Bound the TX queue: if the host stopped draining MIDI-IN (e.g. editor closed without a BYE
|
||||
// while sync_armed), drop the message rather than grow the heap forever. The 5 s heartbeat
|
||||
// re-syncs once the host returns.
|
||||
if self.tx_q.len() > 256 {
|
||||
return;
|
||||
}
|
||||
let mut f: Vec<u8> = Vec::with_capacity(text.len() + 4);
|
||||
f.push(0xF0);
|
||||
f.push(0x7D);
|
||||
|
|
|
|||
Loading…
Reference in a new issue