fix: make it cancellable; on success, return process 1000, on error process 0 with an error message

This commit is contained in:
Hocuri
2026-09-17 19:42:55 +02:00
parent 28b1aa6e87
commit d45b2b9d13
2 changed files with 30 additions and 7 deletions

View File

@@ -18,12 +18,14 @@
use std::collections::BTreeSet; use std::collections::BTreeSet;
use std::pin::Pin; use std::pin::Pin;
use std::sync::Arc;
use anyhow::Result; use anyhow::{Result, bail};
use deltachat_contact_tools::{EmailAddress, addr_normalize}; use deltachat_contact_tools::{EmailAddress, addr_normalize};
use rand::distr::{Alphanumeric, SampleString}; use rand::distr::{Alphanumeric, SampleString};
use rand::rng; use rand::rng;
use rand::seq::{IndexedRandom, SliceRandom as _}; use rand::seq::{IndexedRandom, SliceRandom as _};
use tokio::sync::Mutex;
use tokio::task::JoinSet; use tokio::task::JoinSet;
use crate::config::{self, Config}; use crate::config::{self, Config};
@@ -82,10 +84,13 @@ pub(crate) async fn init_transports_inner(
} }
} }
let last_error: Arc<Mutex<String>> = Default::default();
let mut join_set = JoinSet::new(); let mut join_set = JoinSet::new();
for _ in 0..NUM_TRANSPORTS_TARGET { for _ in 0..NUM_TRANSPORTS_TARGET {
let context = context.clone(); let context = context.clone();
let relays_receiver = relays_receiver.clone(); let relays_receiver = relays_receiver.clone();
let last_error = last_error.clone();
join_set.spawn(async move { join_set.spawn(async move {
loop { loop {
// Take a lock in order to prevent other relay management code // Take a lock in order to prevent other relay management code
@@ -99,6 +104,7 @@ pub(crate) async fn init_transports_inner(
let res = crate::configure::configure(&context, &param, skip_network).await; let res = crate::configure::configure(&context, &param, skip_network).await;
if let Err(err) = res { if let Err(err) = res {
warn!(context, "Failed to init transport {host}: {err:#}."); warn!(context, "Failed to init transport {host}: {err:#}.");
*last_error.lock().await = format!("{err:#}");
// Try another relay in the next iteration of the loop // Try another relay in the next iteration of the loop
} else { } else {
if context.count_transports().await.unwrap_or(0) >= NUM_TRANSPORTS_TARGET { if context.count_transports().await.unwrap_or(0) >= NUM_TRANSPORTS_TARGET {
@@ -114,12 +120,16 @@ pub(crate) async fn init_transports_inner(
}); });
} }
while let Some(success) = join_set.join_next().await { loop {
if success? { match join_set.join_next().await {
break; Some(Ok(true)) => break, // success
Some(Ok(false)) => continue, // Wait until one of the other tasks is successful
Some(Err(e)) => warn!(context, "One of the init_transports tasks failed: {e:#}"),
None => bail!(
"Could not configure any relay, are you offline? ({})",
last_error.try_lock()?
),
} }
// If this task was not successful, continue waiting for the other tasks
// because maybe one of the ongoing configuration attempts will be successful
} }
join_set.detach_all(); join_set.detach_all();

View File

@@ -217,8 +217,21 @@ impl Context {
} }
} }
let cancel_channel = self.alloc_ongoing().await?;
let skip_network = false; let skip_network = false;
autorelay::init_transports_inner(self, addrs_from_qr, skip_network).await?; let res = autorelay::init_transports_inner(self, addrs_from_qr, skip_network)
.race(cancel_channel.recv().map(|_| Err(format_err!("Canceled"))))
.await;
self.free_ongoing().await;
if let Err(err) = res {
let error_msg = stock_str::configuration_failed(self, &format!("{err:#}"));
progress!(self, 0, Some(error_msg.clone()));
bail!(error_msg);
}
self.update_device_chats() self.update_device_chats()
.await .await
.context("Failed to update device chats")?; .context("Failed to update device chats")?;