refactor(main): Centralize thread error handling

This commit is contained in:
Nils Andreas Svee committed 2026-02-22 16:58:01 +07:00
1 parent c116dd3e74
commit 1a87372ffb
1 file changed
+53 -25
+53 -25
View File
@@ -123,28 +123,46 @@ fn main() -> anyhow::Result<()> {
); );
sleep(settle_sleep_time); sleep(settle_sleep_time);
let (error_tx, error_rx) = channel::<anyhow::Error>();
let err_tx = error_tx.clone();
let reflector_peers_lock_clone = reflector_peers_lock.clone(); let reflector_peers_lock_clone = reflector_peers_lock.clone();
let receiver_handle = thread::Builder::new().name("receiver".to_string()).spawn( thread::Builder::new().name("receiver".to_string()).spawn(
move || -> anyhow::Result<()> { move || {
pinger_receiver.listen( if let Err(e) = pinger_receiver.listen(
id, id,
config.measurement_type, config.measurement_type,
reflector_peers_lock_clone, reflector_peers_lock_clone,
baseliner_stats_sender, baseliner_stats_sender,
) ) {
}, let _ = err_tx.send(e);
)?; }
let baseliner_handle = thread::Builder::new()
.name("baseliner".to_string())
.spawn(move || -> anyhow::Result<()> { baseliner.run() })?;
let reflector_peers_lock_clone = reflector_peers_lock.clone();
let sender_handle = thread::Builder::new().name("sender".to_string()).spawn(
move || -> anyhow::Result<()> {
pinger_sender.send(id, config.measurement_type, reflector_peers_lock_clone, config.tick_interval)
}, },
)?; )?;
let mut threads = vec![receiver_handle, sender_handle, baseliner_handle]; let err_tx = error_tx.clone();
thread::Builder::new()
.name("baseliner".to_string())
.spawn(move || {
if let Err(e) = baseliner.run() {
let _ = err_tx.send(e);
}
})?;
let err_tx = error_tx.clone();
let reflector_peers_lock_clone = reflector_peers_lock.clone();
thread::Builder::new().name("sender".to_string()).spawn(
move || {
if let Err(e) = pinger_sender.send(
id,
config.measurement_type,
reflector_peers_lock_clone,
config.tick_interval,
) {
let _ = err_tx.send(e);
}
},
)?;
if reflector_pool_size > config.num_reflectors as usize { if reflector_pool_size > config.num_reflectors as usize {
let reflector_selector = ReflectorSelector { let reflector_selector = ReflectorSelector {
@@ -154,10 +172,14 @@ fn main() -> anyhow::Result<()> {
reflector_pool, reflector_pool,
trigger_channel: reselect_receiver, trigger_channel: reselect_receiver,
}; };
let reselection_handle = thread::Builder::new() let err_tx = error_tx.clone();
thread::Builder::new()
.name("reselection".to_string()) .name("reselection".to_string())
.spawn(move || reflector_selector.run())?; .spawn(move || {
threads.push(reselection_handle); if let Err(e) = reflector_selector.run() {
let _ = err_tx.send(e);
}
})?;
} }
// Sleep 10 seconds before we start adjusting speeds // Sleep 10 seconds before we start adjusting speeds
@@ -198,15 +220,21 @@ fn main() -> anyhow::Result<()> {
config.upload_interface, ul_direction config.upload_interface, ul_direction
); );
let ratecontroller_handle = thread::Builder::new() let err_tx = error_tx.clone();
thread::Builder::new()
.name("ratecontroller".to_string()) .name("ratecontroller".to_string())
.spawn(move || ratecontroller.run())?; .spawn(move || {
if let Err(e) = ratecontroller.run() {
threads.push(ratecontroller_handle); let _ = err_tx.send(e);
for thread in threads {
thread.join().expect("Error happened in thread")?;
} }
})?;
Ok(()) // Drop original sender so recv() unblocks if all threads exit cleanly
drop(error_tx);
// Wait for first error
match error_rx.recv() {
Ok(e) => Err(anyhow::anyhow!("thread exited with error: {e}")),
Err(_) => Ok(()), // all senders dropped = all threads exited without error
}
} }