fix(bridge): add error variants and diagnostic logging for IPC
Implements ticket #341 for Sprint 3: - Add DeserializationWithDump and MutexPoisoned variants to BridgeError - Replace .expect("mutex poisoned") with graceful error propagation in LocalBridge and TcpBridge (4 locations) - Log first 256 bytes as hex dump on deserialization failure for debugging malformed payloads - Classify errors in receive_bridge_inputs: BrokenPipe/ConnectionReset → clean shutdown, MutexPoisoned → shutdown, DeserializationWithDump → skip frame (recoverable) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -83,7 +83,10 @@ impl SimBridge for LocalBridge {
|
||||
fn send_snapshot(&self, snapshot: &ObserverSnapshot) -> Result<(), BridgeError> {
|
||||
let payload = rmp_serde::to_vec_named(snapshot)?;
|
||||
|
||||
let mut writer = self.writer.lock().expect("writer mutex poisoned");
|
||||
let mut writer = self
|
||||
.writer
|
||||
.lock()
|
||||
.map_err(|e| BridgeError::MutexPoisoned(format!("writer: {}", e)))?;
|
||||
write_framed(writer.get_mut(), &payload)?;
|
||||
|
||||
tracing::trace!("sent snapshot: tick={}", snapshot.tick);
|
||||
@@ -91,14 +94,33 @@ impl SimBridge for LocalBridge {
|
||||
}
|
||||
|
||||
fn receive_inputs(&self) -> Result<Vec<PlayerInput>, BridgeError> {
|
||||
let mut reader = self.reader.lock().expect("reader mutex poisoned");
|
||||
let mut reader = self
|
||||
.reader
|
||||
.lock()
|
||||
.map_err(|e| BridgeError::MutexPoisoned(format!("reader: {}", e)))?;
|
||||
|
||||
match read_framed(reader.get_mut())? {
|
||||
Some(payload) => {
|
||||
let inputs: Vec<PlayerInput> = rmp_serde::from_slice(&payload)?;
|
||||
tracing::trace!("received {} inputs", inputs.len());
|
||||
Ok(inputs)
|
||||
}
|
||||
Some(payload) => match rmp_serde::from_slice::<Vec<PlayerInput>>(&payload) {
|
||||
Ok(inputs) => {
|
||||
tracing::trace!("received {} inputs", inputs.len());
|
||||
Ok(inputs)
|
||||
}
|
||||
Err(e) => {
|
||||
let dump_len = payload.len().min(256);
|
||||
tracing::error!(
|
||||
"deserialization failed: {}. Raw bytes ({} of {} total): {:02x?}",
|
||||
e,
|
||||
dump_len,
|
||||
payload.len(),
|
||||
&payload[..dump_len]
|
||||
);
|
||||
Err(BridgeError::DeserializationWithDump(format!(
|
||||
"{} (payload {} bytes)",
|
||||
e,
|
||||
payload.len()
|
||||
)))
|
||||
}
|
||||
},
|
||||
None => Err(BridgeError::Disconnected),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user