aboutsummaryrefslogtreecommitdiff
path: root/crates/tor-hsclient/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/tor-hsclient/src')
-rw-r--r--crates/tor-hsclient/src/state.rs31
1 files changed, 12 insertions, 19 deletions
diff --git a/crates/tor-hsclient/src/state.rs b/crates/tor-hsclient/src/state.rs
index a9067bcf0..c35de5ced 100644
--- a/crates/tor-hsclient/src/state.rs
+++ b/crates/tor-hsclient/src/state.rs
@@ -21,6 +21,7 @@ use tor_circmgr::isolation::Isolation;
use tor_error::{Bug, ErrorReport as _, debug_report, error_report, internal};
use tor_hscrypto::pk::HsId;
use tor_netdir::NetDir;
+use tor_rtcompat::scheduler::{TaskHandle, TaskSchedule};
use tor_rtcompat::{Runtime, SpawnExt as _};
use web_time_compat::{Duration, Instant};
@@ -193,9 +194,9 @@ enum ServiceState<D: MockableConnectorData> {
/// We have a task that will close the circuit when required
///
/// This field serves to require construction sites of Open
- /// to demonstrate that there *is* an expiry task.
- /// In the future, it may also serve to cancel old expiry tasks.
- circuit_expiry_task: CircuitExpiryTask,
+ /// to demonstrate that there *is* an expiry task. It also serves
+ /// to cancel old expiry tasks.
+ circuit_expiry_task: TaskHandle,
},
/// We have a task trying to find the service and establish the circuit
///
@@ -225,18 +226,6 @@ impl<D: MockableConnectorData> ServiceState<D> {
/// "Continuation" return type from `obtain_circuit_or_continuation_info`
type Continuation = (Arc<Mutex<Option<ConnError>>>, postage::barrier::Receiver);
-/// Represents a task which is waiting to see when the circuit needs to be expired
-///
-/// TODO: Replace this with a task handle that cancels the task when dropped.
-/// Until then, if the circuit is closed before then, the expiry task will
-/// uselessly wake up some time later.
-#[derive(Debug)] // Not Clone
-struct CircuitExpiryTask {}
-// impl Drop already, partly to allow explicit drop(CircuitExpiryTask) without clippy complaint
-impl Drop for CircuitExpiryTask {
- fn drop(&mut self) {}
-}
-
/// Obtain a circuit from the `Services` table, or return a continuation
///
/// This is the workhorse function for `get_or_launch_connection`.
@@ -636,7 +625,7 @@ impl<D: MockableConnectorData> ServiceState<D> {
table_index: TableIndex,
last_used: Instant,
now: Instant,
- ) -> Result<CircuitExpiryTask, SpawnError> {
+ ) -> Result<TaskHandle, SpawnError> {
/// Returns the duration until expiry, or `None` if it should expire now
fn calculate_expiry_wait(last_used: Instant, now: Instant) -> Option<Duration> {
let expiry = last_used
@@ -653,6 +642,7 @@ impl<D: MockableConnectorData> ServiceState<D> {
}
let mut maybe_wait = calculate_expiry_wait(last_used, now);
+ let (mut schedule, handle) = TaskSchedule::new(connector.runtime.clone());
let () = connector.runtime.spawn({
let connector = connector.clone();
async move {
@@ -661,7 +651,10 @@ impl<D: MockableConnectorData> ServiceState<D> {
// or jumping into the middle of the loop.
loop {
if let Some(yes_wait) = maybe_wait {
- connector.runtime.sleep(yes_wait).await;
+ if schedule.sleep(yes_wait).await.is_err() {
+ // the circuit expiry task has already been canceled
+ break;
+ }
}
// If it's None, we can't rely on that to say we should expire it,
// since that information crossed a time when we didn't hold the lock.
@@ -690,7 +683,7 @@ impl<D: MockableConnectorData> ServiceState<D> {
} => {
debug!("HS connection expires: {hsid:?}");
drop(circuit);
- drop(circuit_expiry_task); // that's us
+ circuit_expiry_task.cancel();
*state = ServiceState::Closed { data, last_used };
break;
}
@@ -700,7 +693,7 @@ impl<D: MockableConnectorData> ServiceState<D> {
}
}
})?;
- Ok(CircuitExpiryTask {})
+ Ok(handle)
}
}