Skip to content

Commit e35a862

Browse files
committed
fix(esplora): propagate thread join failures
1 parent faf520d commit e35a862

File tree

1 file changed

+36
-4
lines changed

1 file changed

+36
-4
lines changed

crates/esplora/src/blocking_ext.rs

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -316,11 +316,17 @@ fn fetch_txs_with_keychain_spks<I: Iterator<Item = Indexed<SpkWithExpectedTxids>
316316
.collect::<Vec<JoinHandle<Result<TxsOfSpkIndex, Error>>>>();
317317

318318
if handles.is_empty() {
319+
if last_index.is_none() {
320+
return Err(Box::new(esplora_client::Error::InvalidResponse));
321+
}
319322
break;
320323
}
321324

322325
for handle in handles {
323-
let (index, txs, evicted) = handle.join().expect("thread must not panic")?;
326+
let handle_result = handle
327+
.join()
328+
.map_err(|_| Box::new(esplora_client::Error::InvalidResponse))?;
329+
let (index, txs, evicted) = handle_result?;
324330
last_index = Some(index);
325331
if !txs.is_empty() {
326332
last_active_index = Some(index);
@@ -417,7 +423,10 @@ fn fetch_txs_with_txids<I: IntoIterator<Item = Txid>>(
417423
}
418424

419425
for handle in handles {
420-
let (txid, tx_info) = handle.join().expect("thread must not panic")?;
426+
let handle_result = handle
427+
.join()
428+
.map_err(|_| Box::new(esplora_client::Error::InvalidResponse))?;
429+
let (txid, tx_info) = handle_result?;
421430
if let Some(tx_info) = tx_info {
422431
if inserted_txs.insert(txid) {
423432
update.txs.push(tx_info.to_tx().into());
@@ -478,7 +487,10 @@ fn fetch_txs_with_outpoints<I: IntoIterator<Item = OutPoint>>(
478487
}
479488

480489
for handle in handles {
481-
if let Some(op_status) = handle.join().expect("thread must not panic")? {
490+
let handle_result = handle
491+
.join()
492+
.map_err(|_| Box::new(esplora_client::Error::InvalidResponse))?;
493+
if let Some(op_status) = handle_result? {
482494
let spend_txid = match op_status.txid {
483495
Some(txid) => txid,
484496
None => continue,
@@ -511,7 +523,7 @@ fn fetch_txs_with_outpoints<I: IntoIterator<Item = OutPoint>>(
511523
#[cfg(test)]
512524
#[cfg_attr(coverage_nightly, coverage(off))]
513525
mod test {
514-
use crate::blocking_ext::{chain_update, fetch_latest_blocks};
526+
use crate::blocking_ext::{chain_update, fetch_latest_blocks, Error};
515527
use bdk_chain::bitcoin;
516528
use bdk_chain::bitcoin::hashes::Hash;
517529
use bdk_chain::bitcoin::Txid;
@@ -529,6 +541,26 @@ mod test {
529541
}};
530542
}
531543

544+
#[test]
545+
fn thread_join_panic_maps_to_error() {
546+
let handle = std::thread::spawn(|| -> Result<(), Error> {
547+
panic!("expected panic for test coverage");
548+
});
549+
550+
let res = (|| -> Result<(), Error> {
551+
let handle_result = handle
552+
.join()
553+
.map_err(|_| Box::new(esplora_client::Error::InvalidResponse))?;
554+
handle_result?;
555+
Ok(())
556+
})();
557+
558+
assert!(matches!(
559+
*res.unwrap_err(),
560+
esplora_client::Error::InvalidResponse
561+
));
562+
}
563+
532564
macro_rules! local_chain {
533565
[ $(($height:expr, $block_hash:expr)), * ] => {{
534566
#[allow(unused_mut)]

0 commit comments

Comments
 (0)