From d45b2b9d13a089475dd921cfa4127b3c2e683dcb Mon Sep 17 00:00:00 2001 From: Hocuri Date: Thu, 17 Sep 2026 19:42:55 +0200 Subject: [PATCH] fix: make it cancellable; on success, return process 1000, on error process 0 with an error message --- src/autorelay.rs | 22 ++++++++++++++++------ src/configure.rs | 15 ++++++++++++++- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/src/autorelay.rs b/src/autorelay.rs index 40aeb45d6..de6c69071 100644 --- a/src/autorelay.rs +++ b/src/autorelay.rs @@ -18,12 +18,14 @@ use std::collections::BTreeSet; use std::pin::Pin; +use std::sync::Arc; -use anyhow::Result; +use anyhow::{Result, bail}; use deltachat_contact_tools::{EmailAddress, addr_normalize}; use rand::distr::{Alphanumeric, SampleString}; use rand::rng; use rand::seq::{IndexedRandom, SliceRandom as _}; +use tokio::sync::Mutex; use tokio::task::JoinSet; use crate::config::{self, Config}; @@ -82,10 +84,13 @@ pub(crate) async fn init_transports_inner( } } + let last_error: Arc> = Default::default(); + let mut join_set = JoinSet::new(); for _ in 0..NUM_TRANSPORTS_TARGET { let context = context.clone(); let relays_receiver = relays_receiver.clone(); + let last_error = last_error.clone(); join_set.spawn(async move { loop { // 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, ¶m, skip_network).await; if let Err(err) = res { warn!(context, "Failed to init transport {host}: {err:#}."); + *last_error.lock().await = format!("{err:#}"); // Try another relay in the next iteration of the loop } else { 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 { - if success? { - break; + loop { + match join_set.join_next().await { + 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(); diff --git a/src/configure.rs b/src/configure.rs index 3a3dbc135..e8102f22f 100644 --- a/src/configure.rs +++ b/src/configure.rs @@ -217,8 +217,21 @@ impl Context { } } + let cancel_channel = self.alloc_ongoing().await?; + 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() .await .context("Failed to update device chats")?;