improve error handling with fatal!()

This commit is contained in:
2026-02-04 11:49:24 -08:00
parent 08871a5782
commit 30b48f686f
3 changed files with 54 additions and 16 deletions

View File

@@ -1,6 +1,14 @@
pub mod sources; pub mod sources;
pub mod targets; pub mod targets;
#[macro_export]
macro_rules! fatal {
($($arg:tt)*) => {{
tracing::error!($($arg)*);
std::process::exit(-1);
}};
}
use async_trait::async_trait; use async_trait::async_trait;
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use figment::{ use figment::{

View File

@@ -206,6 +206,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
debug!("Task setup complete, tasks: {}", tasks.len()); debug!("Task setup complete, tasks: {}", tasks.len());
ctrlc::set_handler(move || { ctrlc::set_handler(move || {
if shutdown_token.is_cancelled() {
info!("Forced shutdown");
std::process::exit(1);
}
info!("Shutting down"); info!("Shutting down");
shutdown_token.cancel() shutdown_token.cancel()
}) })

View File

@@ -15,7 +15,7 @@ use tracing::{debug, debug_span, error, info, instrument, warn};
use crate::{ use crate::{
ChimemonMessage, ChimemonSource, ChimemonSourceChannel, MetricTags, Prs10Config, SourceMetric, ChimemonMessage, ChimemonSource, ChimemonSourceChannel, MetricTags, Prs10Config, SourceMetric,
SourceReport, SourceReportDetails, SourceStatus, SourceReport, SourceReportDetails, SourceStatus, fatal,
}; };
#[derive(Debug)] #[derive(Debug)]
@@ -205,19 +205,28 @@ impl TryFrom<&[u8]> for Prs10Status {
.map(|s| str::from_utf8(s).unwrap().parse::<u8>()) .map(|s| str::from_utf8(s).unwrap().parse::<u8>())
.collect_tuple() .collect_tuple()
.ok_or("Not enough parts in ST reply")?; .ok_or("Not enough parts in ST reply")?;
let volt_lamp_flags = volt_lamp_flags?;
let rf_flags = rf_flags?;
let temp_flags = temp_flags?;
let fll_flags = fll_flags?;
let pps_flags = pps_flags?;
let system_flags = system_flags?;
Ok(Self { Ok(Self {
volt_lamp_flags: Prs10PowerLampFlags::from_bits(volt_lamp_flags?) volt_lamp_flags: Prs10PowerLampFlags::from_bits(volt_lamp_flags).ok_or_else(|| {
.ok_or("Invalid bits set ({volt_lamp_flags}) for power/lamp flags")?, format!("Invalid bits set ({volt_lamp_flags}) for power/lamp flags")
rf_flags: Prs10RfFlags::from_bits(rf_flags?) })?,
.ok_or("Invalid bits set ({rf_flags}) for RF flags")?, rf_flags: Prs10RfFlags::from_bits(rf_flags)
temp_flags: Prs10TempFlags::from_bits(temp_flags?) .ok_or_else(|| format!("Invalid bits set ({rf_flags}) for RF flags"))?,
.ok_or("Invalid bits set ({temp_flags}) for temp flags")?, temp_flags: Prs10TempFlags::from_bits(temp_flags)
fll_flags: Prs10FllFlags::from_bits(fll_flags?) .ok_or_else(|| format!("Invalid bits set ({temp_flags}) for temp flags"))?,
.ok_or("Invalid bits set ({fll_flags}) for FLL flags")?, fll_flags: Prs10FllFlags::from_bits(fll_flags)
pps_flags: Prs10PpsFlags::from_bits(pps_flags?) .ok_or_else(|| format!("Invalid bits set ({fll_flags}) for FLL flags"))?,
.ok_or("Invalid bits set ({pps_flags}) for PPS flags")?, pps_flags: Prs10PpsFlags::from_bits(pps_flags)
system_flags: Prs10SystemFlags::from_bits(system_flags?) .ok_or_else(|| format!("Invalid bits set ({pps_flags}) for PPS flags"))?,
.ok_or("Invalid bits set ({system_flags}) for system flags")?, system_flags: Prs10SystemFlags::from_bits(system_flags)
.ok_or_else(|| format!("Invalid bits set ({system_flags}) for system flags"))?,
}) })
} }
} }
@@ -488,8 +497,20 @@ impl ChimemonSource for Prs10Monitor {
.parity(tokio_serial::Parity::None) .parity(tokio_serial::Parity::None)
.stop_bits(tokio_serial::StopBits::One) .stop_bits(tokio_serial::StopBits::One)
.flow_control(tokio_serial::FlowControl::None); .flow_control(tokio_serial::FlowControl::None);
let mut port = SerialStream::open(&builder).expect("Must be able to open serial port"); let mut port = SerialStream::open(&builder).unwrap_or_else(|e| {
port.set_exclusive(true).expect("Can't lock serial port"); fatal!(
"Failed to open serial port `{}` ({})",
config.port,
e.to_string()
)
});
port.set_exclusive(true).unwrap_or_else(|e| {
fatal!(
"Can't lock serial port `{}` ({})",
config.port,
e.to_string()
)
});
info!( info!(
"Opened serial port {}@{}", "Opened serial port {}@{}",
port.name().unwrap(), port.name().unwrap(),
@@ -505,10 +526,15 @@ impl ChimemonSource for Prs10Monitor {
info: OnceCell::new(), info: OnceCell::new(),
} }
} }
async fn run(mut self, chan: ChimemonSourceChannel, cancel: CancellationToken) { async fn run(mut self, chan: ChimemonSourceChannel, cancel: CancellationToken) {
info!("PRS10 task started"); info!("PRS10 task started");
if let Err(e) = self.reset_rx_state().await {
error!(error = ?e, "Error clearing PRS10 RX state");
return;
}
if let Err(e) = self.set_info().await { if let Err(e) = self.set_info().await {
error!("Error starting PRS10: {e:?}"); error!(error = ?e, "Error starting PRS10");
return; return;
} }
info!( info!(