diff --git a/crates/arti/src/dns.rs b/crates/arti/src/dns.rs
index 034daa2a0ca7a3a3eb2e8baa4ca752ad81138860..8e3970c9bc14477eda57b64b3b538507331a94aa 100644
--- a/crates/arti/src/dns.rs
+++ b/crates/arti/src/dns.rs
@@ -19,6 +19,9 @@ use tor_rtcompat::{Runtime, UdpSocket};
 
 use anyhow::{anyhow, Result};
 
+/// Maximum lenght for receiving a single datagram
+const MAX_DATAGRAM_SIZE: usize = 1536;
+
 /// Send an error DNS response with code NotImplemented
 async fn not_implemented<U: UdpSocket>(id: u16, addr: &SocketAddr, socket: &U) -> Result<()> {
     let response = Message::error_msg(id, OpCode::Query, ResponseCode::NotImp);
@@ -133,7 +136,7 @@ pub(crate) async fn run_dns_resolver<R: Runtime>(
     // We weren't able to bind any ports: There's nothing to do.
     if listeners.is_empty() {
         error!("Couldn't open any DNS listeners.");
-        return Err(anyhow!("Couldn't open SOCKS listeners"));
+        return Err(anyhow!("Couldn't open any DNS listeners"));
     }
 
     let mut incoming = futures::stream::select_all(
@@ -141,7 +144,7 @@ pub(crate) async fn run_dns_resolver<R: Runtime>(
             .into_iter()
             .map(|socket| {
                 futures::stream::unfold(Arc::new(socket), |socket| async {
-                    let mut packet = [0; 1536];
+                    let mut packet = [0; MAX_DATAGRAM_SIZE];
                     let packet = socket
                         .recv(&mut packet)
                         .await
diff --git a/crates/arti/src/lib.rs b/crates/arti/src/lib.rs
index 87dbd7759d42dee38920d3a8ff808c69b851f032..e4d357d7c10dde2026bacd0eb87b963cc85a0d07 100644
--- a/crates/arti/src/lib.rs
+++ b/crates/arti/src/lib.rs
@@ -131,6 +131,9 @@ use tracing::{info, warn};
 
 use std::convert::TryInto;
 
+/// Shorthand for a boxed and pinned Future.
+type PinnedFuture<T> = std::pin::Pin<Box<dyn futures::Future<Output = T>>>;
+
 /// Run the main loop of the proxy.
 ///
 /// # Panics
@@ -156,21 +159,23 @@ pub async fn run<R: Runtime>(
         watch_cfg::watch_for_config_changes(config_sources, arti_config, client.clone())?;
     }
 
-    let mut proxy: Vec<std::pin::Pin<Box<dyn futures::Future<Output = Result<()>>>>> = Vec::new();
+    let mut proxy: Vec<PinnedFuture<(Result<()>, &str)>> = Vec::new();
     if socks_port != 0 {
-        proxy.push(Box::pin(socks::run_socks_proxy(
-            runtime.clone(),
-            client.isolated_client(),
-            socks_port,
-        )));
+        let runtime = runtime.clone();
+        let client = client.isolated_client();
+        proxy.push(Box::pin(async move {
+            let res = socks::run_socks_proxy(runtime, client, socks_port).await;
+            (res, "SOCKS")
+        }));
     }
 
     if dns_port != 0 {
-        proxy.push(Box::pin(dns::run_dns_resolver(
-            runtime.clone(),
-            client.isolated_client(),
-            dns_port,
-        )));
+        let runtime = runtime.clone();
+        let client = client.isolated_client();
+        proxy.push(Box::pin(async move {
+            let res = dns::run_dns_resolver(runtime, client, dns_port).await;
+            (res, "DNS")
+        }));
     }
 
     if proxy.is_empty() {
@@ -179,12 +184,12 @@ pub async fn run<R: Runtime>(
         return Ok(());
     }
 
-    let proxy = futures::future::select_all(proxy);
+    let proxy = futures::future::select_all(proxy).map(|(finished, _index, _others)| finished);
     futures::select!(
         r = exit::wait_for_ctrl_c().fuse()
             => r.context("waiting for termination signal"),
         r = proxy.fuse()
-            => r.0.context("SOCKS proxy failure"),
+            => r.0.context(format!("{} proxy failure", r.1)),
         r = async {
             client.bootstrap().await?;
             info!("Sufficiently bootstrapped; system SOCKS now functional.");
diff --git a/crates/tor-rtcompat/src/traits.rs b/crates/tor-rtcompat/src/traits.rs
index 6901a891fc79cf807c105c09abc121364a8be932..7c028d57db67dff8cf1d8e4e9d3de0f73f8555ad 100644
--- a/crates/tor-rtcompat/src/traits.rs
+++ b/crates/tor-rtcompat/src/traits.rs
@@ -204,7 +204,7 @@ pub trait UdpSocket {
     /// Connect to a remote address. After calling this [`UdpSocket::recv`] may only
     /// return that same address, and the target provided to [`UdpSocket::send`] must
     /// be this address.
-    // rational for taking &mut self: this changes the behavior of the whole socket,
+    // rationale for taking &mut self: this changes the behavior of the whole socket,
     // so it should probably only be used when you have ownership of the socket and
     // not when sharing it.
     async fn connect(&mut self, addr: &SocketAddr) -> IoResult<()>;