From e01f07d72a224ff0427dac70db544a12c2c0bf8c Mon Sep 17 00:00:00 2001 From: Pascal Hertleif Date: Thu, 21 Nov 2019 00:22:06 +0100 Subject: [PATCH 1/3] Add context to more errors cc #569 --- src/fs/canonicalize.rs | 8 ++++- src/fs/copy.rs | 7 ++++- src/fs/create_dir.rs | 7 ++++- src/fs/create_dir_all.rs | 7 ++++- src/fs/file.rs | 7 ++--- src/fs/hard_link.rs | 12 +++++++- src/fs/read.rs | 6 +++- src/fs/read_dir.rs | 12 +++++--- src/fs/read_link.rs | 8 ++++- src/fs/read_to_string.rs | 7 ++++- src/fs/remove_dir.rs | 7 ++++- src/fs/remove_dir_all.rs | 7 ++++- src/fs/remove_file.rs | 7 ++++- src/fs/rename.rs | 12 +++++++- src/fs/write.rs | 7 ++++- src/io/copy.rs | 7 +++-- src/io/stdin.rs | 4 ++- src/net/tcp/listener.rs | 9 ++++-- src/net/tcp/stream.rs | 13 ++++++-- src/net/udp/mod.rs | 64 +++++++++++++++++++++++++++++++++++----- tests/verbose_errors.rs | 2 +- 21 files changed, 181 insertions(+), 39 deletions(-) diff --git a/src/fs/canonicalize.rs b/src/fs/canonicalize.rs index 6eb6977d..38a5a6b9 100644 --- a/src/fs/canonicalize.rs +++ b/src/fs/canonicalize.rs @@ -1,6 +1,7 @@ use crate::io; use crate::path::{Path, PathBuf}; use crate::task::spawn_blocking; +use crate::utils::Context as _; /// Returns the canonical form of a path. /// @@ -32,5 +33,10 @@ use crate::task::spawn_blocking; /// ``` pub async fn canonicalize>(path: P) -> io::Result { let path = path.as_ref().to_owned(); - spawn_blocking(move || std::fs::canonicalize(&path).map(Into::into)).await + spawn_blocking(move || { + std::fs::canonicalize(&path) + .map(Into::into) + .context(|| format!("could not canonicalize `{}`", path.display())) + }) + .await } diff --git a/src/fs/copy.rs b/src/fs/copy.rs index 170b66ec..8fb447bb 100644 --- a/src/fs/copy.rs +++ b/src/fs/copy.rs @@ -1,6 +1,7 @@ use crate::io; use crate::path::Path; use crate::task::spawn_blocking; +use crate::utils::Context as _; /// Copies the contents and permissions of a file to a new location. /// @@ -41,5 +42,9 @@ use crate::task::spawn_blocking; pub async fn copy, Q: AsRef>(from: P, to: Q) -> io::Result { let from = from.as_ref().to_owned(); let to = to.as_ref().to_owned(); - spawn_blocking(move || std::fs::copy(&from, &to)).await + spawn_blocking(move || { + std::fs::copy(&from, &to) + .context(|| format!("could not copy `{}` to `{}`", from.display(), to.display())) + }) + .await } diff --git a/src/fs/create_dir.rs b/src/fs/create_dir.rs index 03c24918..37923c05 100644 --- a/src/fs/create_dir.rs +++ b/src/fs/create_dir.rs @@ -1,6 +1,7 @@ use crate::io; use crate::path::Path; use crate::task::spawn_blocking; +use crate::utils::Context as _; /// Creates a new directory. /// @@ -34,5 +35,9 @@ use crate::task::spawn_blocking; /// ``` pub async fn create_dir>(path: P) -> io::Result<()> { let path = path.as_ref().to_owned(); - spawn_blocking(move || std::fs::create_dir(path)).await + spawn_blocking(move || { + std::fs::create_dir(&path) + .context(|| format!("could not create directory `{}`", path.display())) + }) + .await } diff --git a/src/fs/create_dir_all.rs b/src/fs/create_dir_all.rs index 15241943..753dfd49 100644 --- a/src/fs/create_dir_all.rs +++ b/src/fs/create_dir_all.rs @@ -1,6 +1,7 @@ use crate::io; use crate::path::Path; use crate::task::spawn_blocking; +use crate::utils::Context as _; /// Creates a new directory and all of its parents if they are missing. /// @@ -29,5 +30,9 @@ use crate::task::spawn_blocking; /// ``` pub async fn create_dir_all>(path: P) -> io::Result<()> { let path = path.as_ref().to_owned(); - spawn_blocking(move || std::fs::create_dir_all(path)).await + spawn_blocking(move || { + std::fs::create_dir_all(&path) + .context(|| format!("could not create directory path `{}`", path.display())) + }) + .await } diff --git a/src/fs/file.rs b/src/fs/file.rs index f8242811..24c72c6d 100644 --- a/src/fs/file.rs +++ b/src/fs/file.rs @@ -9,11 +9,11 @@ use std::sync::{Arc, Mutex}; use crate::fs::{Metadata, Permissions}; use crate::future; -use crate::utils::Context as _; use crate::io::{self, Read, Seek, SeekFrom, Write}; use crate::path::Path; use crate::prelude::*; use crate::task::{self, spawn_blocking, Context, Poll, Waker}; +use crate::utils::Context as _; /// An open file on the filesystem. /// @@ -114,8 +114,7 @@ impl File { pub async fn open>(path: P) -> io::Result { let path = path.as_ref().to_owned(); let file = spawn_blocking(move || { - std::fs::File::open(&path) - .context(|| format!("Could not open {}", path.display())) + std::fs::File::open(&path).context(|| format!("Could not open `{}`", path.display())) }) .await?; Ok(File::new(file, true)) @@ -154,7 +153,7 @@ impl File { let path = path.as_ref().to_owned(); let file = spawn_blocking(move || { std::fs::File::create(&path) - .context(|| format!("Could not create {}", path.display())) + .context(|| format!("Could not create `{}`", path.display())) }) .await?; Ok(File::new(file, true)) diff --git a/src/fs/hard_link.rs b/src/fs/hard_link.rs index e6e56cd5..a6a40698 100644 --- a/src/fs/hard_link.rs +++ b/src/fs/hard_link.rs @@ -1,6 +1,7 @@ use crate::io; use crate::path::Path; use crate::task::spawn_blocking; +use crate::utils::Context as _; /// Creates a hard link on the filesystem. /// @@ -32,5 +33,14 @@ use crate::task::spawn_blocking; pub async fn hard_link, Q: AsRef>(from: P, to: Q) -> io::Result<()> { let from = from.as_ref().to_owned(); let to = to.as_ref().to_owned(); - spawn_blocking(move || std::fs::hard_link(&from, &to)).await + spawn_blocking(move || { + std::fs::hard_link(&from, &to).context(|| { + format!( + "could not create a hard link from `{}` to `{}`", + from.display(), + to.display() + ) + }) + }) + .await } diff --git a/src/fs/read.rs b/src/fs/read.rs index ab7d1756..3b568f7a 100644 --- a/src/fs/read.rs +++ b/src/fs/read.rs @@ -1,6 +1,7 @@ use crate::io; use crate::path::Path; use crate::task::spawn_blocking; +use crate::utils::Context as _; /// Reads the entire contents of a file as raw bytes. /// @@ -36,5 +37,8 @@ use crate::task::spawn_blocking; /// ``` pub async fn read>(path: P) -> io::Result> { let path = path.as_ref().to_owned(); - spawn_blocking(move || std::fs::read(path)).await + spawn_blocking(move || { + std::fs::read(&path).context(|| format!("could not read file `{}`", path.display())) + }) + .await } diff --git a/src/fs/read_dir.rs b/src/fs/read_dir.rs index 5e51065b..d8261a94 100644 --- a/src/fs/read_dir.rs +++ b/src/fs/read_dir.rs @@ -1,11 +1,12 @@ -use std::pin::Pin; use std::future::Future; +use std::pin::Pin; use crate::fs::DirEntry; use crate::io; use crate::path::Path; use crate::stream::Stream; use crate::task::{spawn_blocking, Context, JoinHandle, Poll}; +use crate::utils::Context as _; /// Returns a stream of entries in a directory. /// @@ -45,9 +46,12 @@ use crate::task::{spawn_blocking, Context, JoinHandle, Poll}; /// ``` pub async fn read_dir>(path: P) -> io::Result { let path = path.as_ref().to_owned(); - spawn_blocking(move || std::fs::read_dir(path)) - .await - .map(ReadDir::new) + spawn_blocking(move || { + std::fs::read_dir(&path) + .context(|| format!("could not read directory `{}`", path.display())) + }) + .await + .map(ReadDir::new) } /// A stream of entries in a directory. diff --git a/src/fs/read_link.rs b/src/fs/read_link.rs index 7ec18a45..d8cabb72 100644 --- a/src/fs/read_link.rs +++ b/src/fs/read_link.rs @@ -1,6 +1,7 @@ use crate::io; use crate::path::{Path, PathBuf}; use crate::task::spawn_blocking; +use crate::utils::Context as _; /// Reads a symbolic link and returns the path it points to. /// @@ -28,5 +29,10 @@ use crate::task::spawn_blocking; /// ``` pub async fn read_link>(path: P) -> io::Result { let path = path.as_ref().to_owned(); - spawn_blocking(move || std::fs::read_link(path).map(Into::into)).await + spawn_blocking(move || { + std::fs::read_link(&path) + .map(Into::into) + .context(|| format!("could not read link `{}`", path.display())) + }) + .await } diff --git a/src/fs/read_to_string.rs b/src/fs/read_to_string.rs index d06aa614..2378aaed 100644 --- a/src/fs/read_to_string.rs +++ b/src/fs/read_to_string.rs @@ -1,6 +1,7 @@ use crate::io; use crate::path::Path; use crate::task::spawn_blocking; +use crate::utils::Context as _; /// Reads the entire contents of a file as a string. /// @@ -37,5 +38,9 @@ use crate::task::spawn_blocking; /// ``` pub async fn read_to_string>(path: P) -> io::Result { let path = path.as_ref().to_owned(); - spawn_blocking(move || std::fs::read_to_string(path)).await + spawn_blocking(move || { + std::fs::read_to_string(&path) + .context(|| format!("could not read file `{}`", path.display())) + }) + .await } diff --git a/src/fs/remove_dir.rs b/src/fs/remove_dir.rs index 1a62db2e..8fdba18c 100644 --- a/src/fs/remove_dir.rs +++ b/src/fs/remove_dir.rs @@ -1,6 +1,7 @@ use crate::io; use crate::path::Path; use crate::task::spawn_blocking; +use crate::utils::Context as _; /// Removes an empty directory. /// @@ -29,5 +30,9 @@ use crate::task::spawn_blocking; /// ``` pub async fn remove_dir>(path: P) -> io::Result<()> { let path = path.as_ref().to_owned(); - spawn_blocking(move || std::fs::remove_dir(path)).await + spawn_blocking(move || { + std::fs::remove_dir(&path) + .context(|| format!("could not remove directory `{}`", path.display())) + }) + .await } diff --git a/src/fs/remove_dir_all.rs b/src/fs/remove_dir_all.rs index 33667406..d4bad3a2 100644 --- a/src/fs/remove_dir_all.rs +++ b/src/fs/remove_dir_all.rs @@ -1,6 +1,7 @@ use crate::io; use crate::path::Path; use crate::task::spawn_blocking; +use crate::utils::Context as _; /// Removes a directory and all of its contents. /// @@ -29,5 +30,9 @@ use crate::task::spawn_blocking; /// ``` pub async fn remove_dir_all>(path: P) -> io::Result<()> { let path = path.as_ref().to_owned(); - spawn_blocking(move || std::fs::remove_dir_all(path)).await + spawn_blocking(move || { + std::fs::remove_dir_all(&path) + .context(|| format!("could not remove directory `{}`", path.display())) + }) + .await } diff --git a/src/fs/remove_file.rs b/src/fs/remove_file.rs index 9a74ec11..b881f8be 100644 --- a/src/fs/remove_file.rs +++ b/src/fs/remove_file.rs @@ -1,6 +1,7 @@ use crate::io; use crate::path::Path; use crate::task::spawn_blocking; +use crate::utils::Context as _; /// Removes a file. /// @@ -29,5 +30,9 @@ use crate::task::spawn_blocking; /// ``` pub async fn remove_file>(path: P) -> io::Result<()> { let path = path.as_ref().to_owned(); - spawn_blocking(move || std::fs::remove_file(path)).await + spawn_blocking(move || { + std::fs::remove_file(&path) + .context(|| format!("could not remove file `{}`", path.display())) + }) + .await } diff --git a/src/fs/rename.rs b/src/fs/rename.rs index ed7f39c9..25fc55fa 100644 --- a/src/fs/rename.rs +++ b/src/fs/rename.rs @@ -1,6 +1,7 @@ use crate::io; use crate::path::Path; use crate::task::spawn_blocking; +use crate::utils::Context as _; /// Renames a file or directory to a new location. /// @@ -34,5 +35,14 @@ use crate::task::spawn_blocking; pub async fn rename, Q: AsRef>(from: P, to: Q) -> io::Result<()> { let from = from.as_ref().to_owned(); let to = to.as_ref().to_owned(); - spawn_blocking(move || std::fs::rename(&from, &to)).await + spawn_blocking(move || { + std::fs::rename(&from, &to).context(|| { + format!( + "could not rename `{}` to `{}`", + from.display(), + to.display() + ) + }) + }) + .await } diff --git a/src/fs/write.rs b/src/fs/write.rs index 4e5d20bb..7c14098b 100644 --- a/src/fs/write.rs +++ b/src/fs/write.rs @@ -1,6 +1,7 @@ use crate::io; use crate::path::Path; use crate::task::spawn_blocking; +use crate::utils::Context as _; /// Writes a slice of bytes as the new contents of a file. /// @@ -33,5 +34,9 @@ use crate::task::spawn_blocking; pub async fn write, C: AsRef<[u8]>>(path: P, contents: C) -> io::Result<()> { let path = path.as_ref().to_owned(); let contents = contents.as_ref().to_owned(); - spawn_blocking(move || std::fs::write(path, contents)).await + spawn_blocking(move || { + std::fs::write(&path, contents) + .context(|| format!("could not write to file `{}`", path.display())) + }) + .await } diff --git a/src/io/copy.rs b/src/io/copy.rs index 8ec3c1af..f05ed0e1 100644 --- a/src/io/copy.rs +++ b/src/io/copy.rs @@ -1,10 +1,11 @@ -use std::pin::Pin; use std::future::Future; +use std::pin::Pin; use pin_project_lite::pin_project; use crate::io::{self, BufRead, BufReader, Read, Write}; use crate::task::{Context, Poll}; +use crate::utils::Context as _; /// Copies the entire contents of a reader into a writer. /// @@ -90,7 +91,7 @@ where writer, amt: 0, }; - future.await + future.await.context(|| String::from("io::copy failed")) } /// Copies the entire contents of a reader into a writer. @@ -177,5 +178,5 @@ where writer, amt: 0, }; - future.await + future.await.context(|| String::from("io::copy failed")) } diff --git a/src/io/stdin.rs b/src/io/stdin.rs index 167ea2dd..618393af 100644 --- a/src/io/stdin.rs +++ b/src/io/stdin.rs @@ -1,10 +1,11 @@ +use std::future::Future; use std::pin::Pin; use std::sync::Mutex; -use std::future::Future; use crate::future; use crate::io::{self, Read}; use crate::task::{spawn_blocking, Context, JoinHandle, Poll}; +use crate::utils::Context as _; cfg_unstable! { use once_cell::sync::Lazy; @@ -162,6 +163,7 @@ impl Stdin { } }) .await + .context(|| String::from("Could not read line on stdin")) } /// Locks this handle to the standard input stream, returning a readable guard. diff --git a/src/net/tcp/listener.rs b/src/net/tcp/listener.rs index f98bbdc7..9d944f4b 100644 --- a/src/net/tcp/listener.rs +++ b/src/net/tcp/listener.rs @@ -1,5 +1,5 @@ -use std::net::SocketAddr; use std::future::Future; +use std::net::SocketAddr; use std::pin::Pin; use crate::future; @@ -8,6 +8,7 @@ use crate::net::driver::Watcher; use crate::net::{TcpStream, ToSocketAddrs}; use crate::stream::Stream; use crate::task::{Context, Poll}; +use crate::utils::Context as _; /// A TCP socket server, listening for connections. /// @@ -75,8 +76,12 @@ impl TcpListener { /// [`local_addr`]: #method.local_addr pub async fn bind(addrs: A) -> io::Result { let mut last_err = None; + let addrs = addrs + .to_socket_addrs() + .await + .context(|| String::from("could not resolve addresses"))?; - for addr in addrs.to_socket_addrs().await? { + for addr in addrs { match mio::net::TcpListener::bind(&addr) { Ok(mio_listener) => { return Ok(TcpListener { diff --git a/src/net/tcp/stream.rs b/src/net/tcp/stream.rs index 1da9c7c2..9d3c2ecd 100644 --- a/src/net/tcp/stream.rs +++ b/src/net/tcp/stream.rs @@ -7,6 +7,7 @@ use crate::io::{self, Read, Write}; use crate::net::driver::Watcher; use crate::net::ToSocketAddrs; use crate::task::{spawn_blocking, Context, Poll}; +use crate::utils::Context as _; /// A TCP stream between a local and a remote socket. /// @@ -71,11 +72,17 @@ impl TcpStream { /// ``` pub async fn connect(addrs: A) -> io::Result { let mut last_err = None; + let addrs = addrs + .to_socket_addrs() + .await + .context(|| String::from("could not resolve addresses"))?; - for addr in addrs.to_socket_addrs().await? { + for addr in addrs { let res = spawn_blocking(move || { - let std_stream = std::net::TcpStream::connect(addr)?; - let mio_stream = mio::net::TcpStream::from_stream(std_stream)?; + let std_stream = std::net::TcpStream::connect(addr) + .context(|| format!("could not connect to {}", addr))?; + let mio_stream = mio::net::TcpStream::from_stream(std_stream) + .context(|| format!("could not open async connection to {}", addr))?; Ok(TcpStream { watcher: Watcher::new(mio_stream), }) diff --git a/src/net/udp/mod.rs b/src/net/udp/mod.rs index 37c9d50c..e6064136 100644 --- a/src/net/udp/mod.rs +++ b/src/net/udp/mod.rs @@ -5,6 +5,7 @@ use std::net::{Ipv4Addr, Ipv6Addr}; use crate::future; use crate::net::driver::Watcher; use crate::net::ToSocketAddrs; +use crate::utils::Context as _; /// A UDP socket. /// @@ -66,10 +67,14 @@ impl UdpSocket { /// # /// # Ok(()) }) } /// ``` - pub async fn bind(addr: A) -> io::Result { + pub async fn bind(addrs: A) -> io::Result { let mut last_err = None; + let addrs = addrs + .to_socket_addrs() + .await + .context(|| String::from("could not resolve addresses"))?; - for addr in addr.to_socket_addrs().await? { + for addr in addrs { match mio::net::UdpSocket::bind(&addr) { Ok(mio_socket) => { return Ok(UdpSocket { @@ -106,7 +111,10 @@ impl UdpSocket { /// # Ok(()) }) } /// ``` pub fn local_addr(&self) -> io::Result { - self.watcher.get_ref().local_addr() + self.watcher + .get_ref() + .local_addr() + .context(|| String::from("could not get local address")) } /// Sends data on the socket to the given address. @@ -151,6 +159,7 @@ impl UdpSocket { .poll_write_with(cx, |inner| inner.send_to(buf, &addr)) }) .await + .context(|| format!("Could not send packet to {}", addr)) } /// Receives data from the socket. @@ -178,6 +187,17 @@ impl UdpSocket { .poll_read_with(cx, |inner| inner.recv_from(buf)) }) .await + .context(|| { + use std::fmt::Write; + + let mut error = String::from("Could not receive data on "); + if let Ok(addr) = self.local_addr() { + let _ = write!(&mut error, "{}", addr); + } else { + error.push_str("socket"); + } + error + }) } /// Connects the UDP socket to a remote address. @@ -195,7 +215,7 @@ impl UdpSocket { /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # - /// use async_std::net::UdpSocket; + /// use async_std::net::UdpSocket; /// /// let socket = UdpSocket::bind("127.0.0.1:0").await?; /// socket.connect("127.0.0.1:8080").await?; @@ -204,8 +224,12 @@ impl UdpSocket { /// ``` pub async fn connect(&self, addrs: A) -> io::Result<()> { let mut last_err = None; + let addrs = addrs + .to_socket_addrs() + .await + .context(|| String::from("could not resolve addresses"))?; - for addr in addrs.to_socket_addrs().await? { + for addr in addrs { // TODO(stjepang): connect on the blocking pool match self.watcher.get_ref().connect(addr) { Ok(()) => return Ok(()), @@ -248,7 +272,19 @@ impl UdpSocket { /// # Ok(()) }) } /// ``` pub async fn send(&self, buf: &[u8]) -> io::Result { - future::poll_fn(|cx| self.watcher.poll_write_with(cx, |inner| inner.send(buf))).await + future::poll_fn(|cx| self.watcher.poll_write_with(cx, |inner| inner.send(buf))) + .await + .context(|| { + use std::fmt::Write; + + let mut error = String::from("Could not send data on "); + if let Ok(addr) = self.local_addr() { + let _ = write!(&mut error, "{}", addr); + } else { + error.push_str("socket"); + } + error + }) } /// Receives data from the socket. @@ -271,7 +307,19 @@ impl UdpSocket { /// # Ok(()) }) } /// ``` pub async fn recv(&self, buf: &mut [u8]) -> io::Result { - future::poll_fn(|cx| self.watcher.poll_read_with(cx, |inner| inner.recv(buf))).await + future::poll_fn(|cx| self.watcher.poll_read_with(cx, |inner| inner.recv(buf))) + .await + .context(|| { + use std::fmt::Write; + + let mut error = String::from("Could not receive data on "); + if let Ok(addr) = self.local_addr() { + let _ = write!(&mut error, "{}", addr); + } else { + error.push_str("socket"); + } + error + }) } /// Gets the value of the `SO_BROADCAST` option for this socket. @@ -415,7 +463,7 @@ impl UdpSocket { /// use async_std::net::UdpSocket; /// /// let socket_addr = SocketAddr::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0).into(), 0); - /// let mdns_addr = Ipv6Addr::new(0xFF02, 0, 0, 0, 0, 0, 0, 0x0123) ; + /// let mdns_addr = Ipv6Addr::new(0xFF02, 0, 0, 0, 0, 0, 0, 0x0123); /// let socket = UdpSocket::bind(&socket_addr).await?; /// /// socket.join_multicast_v6(&mdns_addr, 0)?; diff --git a/tests/verbose_errors.rs b/tests/verbose_errors.rs index 54d04f8d..207d0b27 100644 --- a/tests/verbose_errors.rs +++ b/tests/verbose_errors.rs @@ -8,7 +8,7 @@ fn open_file() { match res { Ok(_) => panic!("Found file with random name: We live in a simulation"), Err(e) => assert_eq!( - "Could not open /ashjudlkahasdasdsikdhajik/asdasdasdasdasdasd/fjuiklashdbflasas", + "Could not open `/ashjudlkahasdasdsikdhajik/asdasdasdasdasdasd/fjuiklashdbflasas`", &format!("{}", e) ), } From aa7d1c27a42b262ef47a68e0fb61f5078fb18a33 Mon Sep 17 00:00:00 2001 From: Pascal Hertleif Date: Mon, 25 Nov 2019 21:18:40 +0100 Subject: [PATCH 2/3] Verbose errors: Apply suggestions Co-Authored-By: Yoshua Wuyts --- src/fs/file.rs | 4 ++-- src/io/stdin.rs | 2 +- src/net/udp/mod.rs | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/fs/file.rs b/src/fs/file.rs index 24c72c6d..c111e013 100644 --- a/src/fs/file.rs +++ b/src/fs/file.rs @@ -114,7 +114,7 @@ impl File { pub async fn open>(path: P) -> io::Result { let path = path.as_ref().to_owned(); let file = spawn_blocking(move || { - std::fs::File::open(&path).context(|| format!("Could not open `{}`", path.display())) + std::fs::File::open(&path).context(|| format!("could not open `{}`", path.display())) }) .await?; Ok(File::new(file, true)) @@ -153,7 +153,7 @@ impl File { let path = path.as_ref().to_owned(); let file = spawn_blocking(move || { std::fs::File::create(&path) - .context(|| format!("Could not create `{}`", path.display())) + .context(|| format!("could not create `{}`", path.display())) }) .await?; Ok(File::new(file, true)) diff --git a/src/io/stdin.rs b/src/io/stdin.rs index 618393af..369ccae4 100644 --- a/src/io/stdin.rs +++ b/src/io/stdin.rs @@ -163,7 +163,7 @@ impl Stdin { } }) .await - .context(|| String::from("Could not read line on stdin")) + .context(|| String::from("could not read line on stdin")) } /// Locks this handle to the standard input stream, returning a readable guard. diff --git a/src/net/udp/mod.rs b/src/net/udp/mod.rs index e6064136..a1ca03f3 100644 --- a/src/net/udp/mod.rs +++ b/src/net/udp/mod.rs @@ -159,7 +159,7 @@ impl UdpSocket { .poll_write_with(cx, |inner| inner.send_to(buf, &addr)) }) .await - .context(|| format!("Could not send packet to {}", addr)) + .context(|| format!("could not send packet to {}", addr)) } /// Receives data from the socket. @@ -190,7 +190,7 @@ impl UdpSocket { .context(|| { use std::fmt::Write; - let mut error = String::from("Could not receive data on "); + let mut error = String::from("could not receive data on "); if let Ok(addr) = self.local_addr() { let _ = write!(&mut error, "{}", addr); } else { @@ -277,7 +277,7 @@ impl UdpSocket { .context(|| { use std::fmt::Write; - let mut error = String::from("Could not send data on "); + let mut error = String::from("could not send data on "); if let Ok(addr) = self.local_addr() { let _ = write!(&mut error, "{}", addr); } else { @@ -312,7 +312,7 @@ impl UdpSocket { .context(|| { use std::fmt::Write; - let mut error = String::from("Could not receive data on "); + let mut error = String::from("could not receive data on "); if let Ok(addr) = self.local_addr() { let _ = write!(&mut error, "{}", addr); } else { From 56538ebd9117402d2c8e69a67a08b4ea8b5e660f Mon Sep 17 00:00:00 2001 From: Pascal Hertleif Date: Mon, 25 Nov 2019 21:41:54 +0100 Subject: [PATCH 3/3] Improve verbose errors for socket addresses Moves the point of adding error context to the net::addr module so that we have access to the raw address input and can include it in the error message. --- src/net/addr.rs | 32 +++++++++++++++++++++++++++----- src/net/tcp/listener.rs | 4 +--- src/net/tcp/stream.rs | 3 +-- src/net/udp/mod.rs | 3 +-- tests/verbose_errors.rs | 17 ++++++++++++++++- 5 files changed, 46 insertions(+), 13 deletions(-) diff --git a/src/net/addr.rs b/src/net/addr.rs index 2769dd5e..ea839500 100644 --- a/src/net/addr.rs +++ b/src/net/addr.rs @@ -1,11 +1,12 @@ +use std::future::Future; use std::mem; use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; use std::net::{SocketAddr, SocketAddrV4, SocketAddrV6}; use std::pin::Pin; -use std::future::Future; use crate::io; use crate::task::{spawn_blocking, Context, JoinHandle, Poll}; +use crate::utils::Context as ErrorContext; cfg_not_docs! { macro_rules! ret { @@ -67,6 +68,18 @@ pub enum ToSocketAddrsFuture { Done, } +/// Wrap `std::io::Error` with additional message +/// +/// Keeps the original error kind and stores the original I/O error as `source`. +impl ErrorContext for ToSocketAddrsFuture { + fn context(self, message: impl Fn() -> String) -> Self { + match self { + ToSocketAddrsFuture::Ready(res) => ToSocketAddrsFuture::Ready(res.context(message)), + x => x, + } + } +} + impl> Future for ToSocketAddrsFuture { type Output = io::Result; @@ -110,7 +123,9 @@ impl ToSocketAddrs for SocketAddrV4 { impl Future, ToSocketAddrsFuture ) { - SocketAddr::V4(*self).to_socket_addrs() + SocketAddr::V4(*self) + .to_socket_addrs() + .context(|| format!("could not resolve address `{}`", self)) } } @@ -123,7 +138,9 @@ impl ToSocketAddrs for SocketAddrV6 { impl Future, ToSocketAddrsFuture ) { - SocketAddr::V6(*self).to_socket_addrs() + SocketAddr::V6(*self) + .to_socket_addrs() + .context(|| format!("could not resolve address `{}`", self)) } } @@ -195,7 +212,9 @@ impl ToSocketAddrs for (&str, u16) { let host = host.to_string(); let task = spawn_blocking(move || { - std::net::ToSocketAddrs::to_socket_addrs(&(host.as_str(), port)) + let addr = (host.as_str(), port); + std::net::ToSocketAddrs::to_socket_addrs(&addr) + .context(|| format!("could not resolve address `{:?}`", addr)) }); ToSocketAddrsFuture::Resolving(task) } @@ -215,7 +234,10 @@ impl ToSocketAddrs for str { } let addr = self.to_string(); - let task = spawn_blocking(move || std::net::ToSocketAddrs::to_socket_addrs(addr.as_str())); + let task = spawn_blocking(move || { + std::net::ToSocketAddrs::to_socket_addrs(addr.as_str()) + .context(|| format!("could not resolve address `{:?}`", addr)) + }); ToSocketAddrsFuture::Resolving(task) } } diff --git a/src/net/tcp/listener.rs b/src/net/tcp/listener.rs index 9d944f4b..fe06a96d 100644 --- a/src/net/tcp/listener.rs +++ b/src/net/tcp/listener.rs @@ -8,7 +8,6 @@ use crate::net::driver::Watcher; use crate::net::{TcpStream, ToSocketAddrs}; use crate::stream::Stream; use crate::task::{Context, Poll}; -use crate::utils::Context as _; /// A TCP socket server, listening for connections. /// @@ -78,8 +77,7 @@ impl TcpListener { let mut last_err = None; let addrs = addrs .to_socket_addrs() - .await - .context(|| String::from("could not resolve addresses"))?; + .await?; for addr in addrs { match mio::net::TcpListener::bind(&addr) { diff --git a/src/net/tcp/stream.rs b/src/net/tcp/stream.rs index 9d3c2ecd..41317833 100644 --- a/src/net/tcp/stream.rs +++ b/src/net/tcp/stream.rs @@ -74,8 +74,7 @@ impl TcpStream { let mut last_err = None; let addrs = addrs .to_socket_addrs() - .await - .context(|| String::from("could not resolve addresses"))?; + .await?; for addr in addrs { let res = spawn_blocking(move || { diff --git a/src/net/udp/mod.rs b/src/net/udp/mod.rs index a1ca03f3..7fef1ed5 100644 --- a/src/net/udp/mod.rs +++ b/src/net/udp/mod.rs @@ -71,8 +71,7 @@ impl UdpSocket { let mut last_err = None; let addrs = addrs .to_socket_addrs() - .await - .context(|| String::from("could not resolve addresses"))?; + .await?; for addr in addrs { match mio::net::UdpSocket::bind(&addr) { diff --git a/tests/verbose_errors.rs b/tests/verbose_errors.rs index 207d0b27..15630928 100644 --- a/tests/verbose_errors.rs +++ b/tests/verbose_errors.rs @@ -1,4 +1,4 @@ -use async_std::{fs, task}; +use async_std::{fs, io, net::ToSocketAddrs, task}; #[test] fn open_file() { @@ -14,3 +14,18 @@ fn open_file() { } }) } + +#[test] +fn resolve_address() { + task::block_on(async { + let non_existing_addr = "ashjudlkahasdasdsikdhajik.asdasdasdasdasdasd.fjuiklashdbflasas:80"; + let res: Result<_, io::Error> = non_existing_addr.to_socket_addrs().await; + match res { + Ok(_) => panic!("Found address with random name: We live in a simulation"), + Err(e) => assert_eq!( + "could not resolve address `\"ashjudlkahasdasdsikdhajik.asdasdasdasdasdasd.fjuiklashdbflasas:80\"`", + &format!("{}", e) + ), + } + }) +}