diff --git a/Cargo.toml b/Cargo.toml index f3b1cc98..cd24a396 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ipc-channel" -version = "0.20.1" +version = "0.21.0" description = "A multiprocess drop-in replacement for Rust channels" authors = ["The Servo Project Developers"] license = "MIT OR Apache-2.0" @@ -31,13 +31,14 @@ win32-trace = [] enable-slow-tests = [] [dependencies] -bincode = "1" +bitcode = { version = "0.6.6", features = ["serde"] } crossbeam-channel = "0.5" fnv = "1.0.3" futures-channel = { version = "0.3.31", optional = true } futures-core = { version = "0.3.31", optional = true } libc = "0.2.162" serde = { version = "1.0", features = ["rc"] } +thiserror = "2.0.12" uuid = { version = "1", features = ["v4"] } [target.'cfg(any(target_os = "linux", target_os = "openbsd", target_os = "freebsd", target_os = "illumos"))'.dependencies] diff --git a/src/asynch.rs b/src/asynch.rs index fed5c60d..905bc878 100644 --- a/src/asynch.rs +++ b/src/asynch.rs @@ -10,6 +10,7 @@ use crate::ipc::{ self, IpcMessage, IpcReceiver, IpcReceiverSet, IpcSelectionResult, IpcSender, OpaqueIpcReceiver, }; +use crate::IpcError; use futures_channel::mpsc::UnboundedReceiver; use futures_channel::mpsc::UnboundedSender; use futures_core::stream::FusedStream; @@ -96,7 +97,7 @@ impl Stream for IpcStream where T: for<'de> Deserialize<'de> + Serialize, { - type Item = Result; + type Item = Result; fn poll_next(mut self: Pin<&mut Self>, ctx: &mut Context) -> Poll> { let recv = Pin::new(&mut self.0); diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 00000000..7987ec98 --- /dev/null +++ b/src/error.rs @@ -0,0 +1,32 @@ +use std::fmt::Display; +use std::io; + +use thiserror::Error; + +#[derive(Debug, Error)] +/// An error that occurs for serialization or deserialization +pub struct SerializationError(#[from] pub(crate) bitcode::Error); + +impl Display for SerializationError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "Serialization error") + } +} + +#[derive(Debug, Error)] +pub enum IpcError { + #[error("Error in decoding or encoding: {0}")] + SerializationError(#[from] SerializationError), + #[error("Error in IO: {0}")] + Io(#[from] io::Error), + #[error("Ipc Disconnected")] + Disconnected, +} + +#[derive(Debug, Error)] +pub enum TryRecvError { + #[error("IPC error")] + IpcError(#[from] IpcError), + #[error("Channel empty")] + Empty, +} diff --git a/src/ipc.rs b/src/ipc.rs index c91a381a..15e2ae9b 100644 --- a/src/ipc.rs +++ b/src/ipc.rs @@ -7,16 +7,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use crate::error::SerializationError; use crate::platform::{self, OsIpcChannel, OsIpcReceiver, OsIpcReceiverSet, OsIpcSender}; use crate::platform::{ OsIpcOneShotServer, OsIpcSelectionResult, OsIpcSharedMemory, OsOpaqueIpcChannel, }; +use crate::{IpcError, TryRecvError}; -use bincode; +use bitcode; use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer}; use std::cell::RefCell; use std::cmp::min; -use std::error::Error as StdError; use std::fmt::{self, Debug, Formatter}; use std::io; use std::marker::PhantomData; @@ -37,57 +38,6 @@ thread_local! { const { RefCell::new(Vec::new()) } } -#[derive(Debug)] -pub enum IpcError { - Bincode(bincode::Error), - Io(io::Error), - Disconnected, -} - -impl fmt::Display for IpcError { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - match *self { - IpcError::Bincode(ref err) => write!(fmt, "bincode error: {err}"), - IpcError::Io(ref err) => write!(fmt, "io error: {err}"), - IpcError::Disconnected => write!(fmt, "disconnected"), - } - } -} - -impl StdError for IpcError { - fn source(&self) -> Option<&(dyn StdError + 'static)> { - match *self { - IpcError::Bincode(ref err) => Some(err), - IpcError::Io(ref err) => Some(err), - IpcError::Disconnected => None, - } - } -} - -#[derive(Debug)] -pub enum TryRecvError { - IpcError(IpcError), - Empty, -} - -impl fmt::Display for TryRecvError { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - match *self { - TryRecvError::IpcError(ref err) => write!(fmt, "ipc error: {err}"), - TryRecvError::Empty => write!(fmt, "empty"), - } - } -} - -impl StdError for TryRecvError { - fn source(&self) -> Option<&(dyn StdError + 'static)> { - match *self { - TryRecvError::IpcError(ref err) => Some(err), - TryRecvError::Empty => None, - } - } -} - /// Create a connected [IpcSender] and [IpcReceiver] that /// transfer messages of a given type provided by type `T` /// or inferred by the types of messages sent by the sender. @@ -248,7 +198,10 @@ where { /// Blocking receive. pub fn recv(&self) -> Result { - self.os_receiver.recv()?.to().map_err(IpcError::Bincode) + self.os_receiver + .recv()? + .to() + .map_err(IpcError::SerializationError) } /// Non-blocking receive @@ -256,7 +209,7 @@ where self.os_receiver .try_recv()? .to() - .map_err(IpcError::Bincode) + .map_err(IpcError::SerializationError) .map_err(TryRecvError::IpcError) } @@ -270,7 +223,7 @@ where self.os_receiver .try_recv_timeout(duration)? .to() - .map_err(IpcError::Bincode) + .map_err(IpcError::SerializationError) .map_err(TryRecvError::IpcError) } @@ -364,7 +317,7 @@ where } /// Send data across the channel to the receiver. - pub fn send(&self, data: T) -> Result<(), bincode::Error> { + pub fn send(&self, data: T) -> Result<(), IpcError> { let mut bytes = Vec::with_capacity(4096); OS_IPC_CHANNELS_FOR_SERIALIZATION.with(|os_ipc_channels_for_serialization| { OS_IPC_SHARED_MEMORY_REGIONS_FOR_SERIALIZATION.with( @@ -377,7 +330,8 @@ where let os_ipc_shared_memory_regions; let os_ipc_channels; { - bincode::serialize_into(&mut bytes, &data)?; + bytes = bitcode::serialize(&data).map_err(SerializationError)?; + os_ipc_channels = mem::replace( &mut *os_ipc_channels_for_serialization.borrow_mut(), old_os_ipc_channels, @@ -726,7 +680,7 @@ impl IpcMessage { } /// Deserialize the raw data in the contained message into the inferred type. - pub fn to(mut self) -> Result + pub fn to(mut self) -> Result where T: for<'de> Deserialize<'de> + Serialize, { @@ -744,7 +698,7 @@ impl IpcMessage { .map(Some) .collect(), ); - let result = bincode::deserialize(&self.data[..]); + let result = bitcode::deserialize(&self.data[..]).map_err(|e| e.into()); *os_ipc_shared_memory_regions_for_deserialization.borrow_mut() = old_ipc_shared_memory_regions_for_deserialization; mem::swap( @@ -886,7 +840,7 @@ where )) } - pub fn accept(self) -> Result<(IpcReceiver, T), bincode::Error> { + pub fn accept(self) -> Result<(IpcReceiver, T), IpcError> { let (os_receiver, ipc_message) = self.os_server.accept()?; Ok(( IpcReceiver { diff --git a/src/lib.rs b/src/lib.rs index 46cdf0bf..da52b326 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -32,6 +32,7 @@ pub mod asynch; #[cfg(all(not(feature = "force-inprocess"), target_os = "windows"))] extern crate windows; +mod error; pub mod ipc; pub mod platform; pub mod router; @@ -39,4 +40,4 @@ pub mod router; #[cfg(test)] mod test; -pub use bincode::{Error, ErrorKind}; +pub use error::{IpcError, TryRecvError}; diff --git a/src/platform/inprocess/mod.rs b/src/platform/inprocess/mod.rs index 2155c737..428ccbe8 100644 --- a/src/platform/inprocess/mod.rs +++ b/src/platform/inprocess/mod.rs @@ -7,13 +7,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::ipc::{self, IpcMessage}; -use bincode; +use crate::ipc::IpcMessage; use crossbeam_channel::{self, Receiver, RecvTimeoutError, Select, Sender, TryRecvError}; use std::cell::{Ref, RefCell}; use std::cmp::PartialEq; use std::collections::hash_map::HashMap; -use std::error::Error as StdError; use std::fmt::{self, Debug, Formatter}; use std::io; use std::ops::{Deref, RangeFrom}; @@ -21,6 +19,7 @@ use std::slice; use std::sync::{Arc, LazyLock, Mutex}; use std::time::Duration; use std::usize; +use thiserror::Error; use uuid::Uuid; #[derive(Clone)] @@ -387,11 +386,15 @@ impl OsIpcSharedMemory { } } -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Error)] pub enum ChannelError { + #[error("Channel Closed")] ChannelClosedError, + #[error("Broken Pipe")] BrokenPipeError, + #[error("Channel Empty")] ChannelEmpty, + #[error("Unknown Error")] UnknownError, } @@ -402,42 +405,23 @@ impl ChannelError { } } -impl fmt::Display for ChannelError { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - match *self { - ChannelError::ChannelClosedError => write!(fmt, "channel closed"), - ChannelError::BrokenPipeError => write!(fmt, "broken pipe"), - ChannelError::ChannelEmpty => write!(fmt, "channel empty"), - ChannelError::UnknownError => write!(fmt, "unknown error"), - } - } -} - -impl StdError for ChannelError {} - -impl From for bincode::Error { - fn from(crossbeam_error: ChannelError) -> Self { - io::Error::from(crossbeam_error).into() - } -} - -impl From for ipc::IpcError { +impl From for crate::IpcError { fn from(error: ChannelError) -> Self { match error { - ChannelError::ChannelClosedError => ipc::IpcError::Disconnected, - e => ipc::IpcError::Bincode(io::Error::from(e).into()), + ChannelError::ChannelClosedError => crate::IpcError::Disconnected, + e => crate::IpcError::Io(io::Error::from(e).into()), } } } -impl From for ipc::TryRecvError { +impl From for crate::TryRecvError { fn from(error: ChannelError) -> Self { match error { ChannelError::ChannelClosedError => { - ipc::TryRecvError::IpcError(ipc::IpcError::Disconnected) + crate::TryRecvError::IpcError(crate::IpcError::Disconnected) }, - ChannelError::ChannelEmpty => ipc::TryRecvError::Empty, - e => ipc::TryRecvError::IpcError(ipc::IpcError::Bincode(io::Error::from(e).into())), + ChannelError::ChannelEmpty => crate::TryRecvError::Empty, + e => crate::TryRecvError::IpcError(crate::IpcError::Io(io::Error::from(e).into())), } } } diff --git a/src/platform/macos/mod.rs b/src/platform/macos/mod.rs index a0935e8a..2716cd71 100644 --- a/src/platform/macos/mod.rs +++ b/src/platform/macos/mod.rs @@ -12,14 +12,12 @@ use self::mach_sys::{kern_return_t, mach_msg_body_t, mach_msg_header_t, mach_msg use self::mach_sys::{mach_msg_ool_descriptor_t, mach_msg_port_descriptor_t, mach_msg_type_name_t}; use self::mach_sys::{mach_msg_timeout_t, mach_port_limits_t, mach_port_msgcount_t}; use self::mach_sys::{mach_port_right_t, mach_port_t, mach_task_self_, vm_inherit_t}; -use crate::ipc::{self, IpcMessage}; +use crate::ipc::IpcMessage; -use bincode; use libc::{self, c_char, c_uint, c_void, size_t}; use rand::{self, Rng}; use std::cell::Cell; use std::convert::TryInto; -use std::error::Error as StdError; use std::ffi::CString; use std::fmt::{self, Debug, Formatter}; use std::io; @@ -30,6 +28,7 @@ use std::ptr; use std::slice; use std::sync::RwLock; use std::time::Duration; +use thiserror::Error; mod mach_sys; @@ -997,43 +996,28 @@ impl Message { } } -#[derive(Clone, Copy, Debug, PartialEq)] +#[derive(Clone, Copy, Debug, Error, PartialEq)] pub enum KernelError { + #[error("Success")] Success, + #[error("No room in IPC name space for another right.")] NoSpace, + #[error("Name doesn't denote a right in the task")] InvalidName, + #[error("Name denotes a right, but not an appropiate right.")] InvalidRight, + #[error("Blatant range error")] InvalidValue, + #[error("The supplied (port) capability is improper")] InvalidCapability, + #[error("Operation would overflow limit on user-references")] UrefsOverflow, + #[error("Receive right is not a member of a port set.")] NotInSet, + #[error("Unkown kernel error. {0}")] Unknown(kern_return_t), } -impl fmt::Display for KernelError { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - match *self { - KernelError::Success => write!(fmt, "Success."), - KernelError::NoSpace => write!(fmt, "No room in IPC name space for another right."), - KernelError::InvalidName => write!(fmt, "Name doesn't denote a right in the task."), - KernelError::InvalidRight => { - write!(fmt, "Name denotes a right, but not an appropriate right.") - }, - KernelError::InvalidValue => write!(fmt, "Blatant range error."), - KernelError::InvalidCapability => { - write!(fmt, "The supplied (port) capability is improper.") - }, - KernelError::UrefsOverflow => { - write!(fmt, "Operation would overflow limit on user-references.") - }, - KernelError::NotInSet => write!(fmt, "Receive right is not a member of a port set."), - KernelError::Unknown(code) => write!(fmt, "Unknown kernel error: {:x}", code), - } - } -} - -impl StdError for KernelError {} - impl From for KernelError { fn from(code: kern_return_t) -> KernelError { match code { @@ -1050,10 +1034,10 @@ impl From for KernelError { } } -#[derive(Clone, Copy, Debug, PartialEq)] +#[derive(Clone, Copy, Debug, Error, PartialEq)] pub enum MachError { Success, - Kernel(KernelError), + Kernel(#[from] KernelError), IpcSpace, VmSpace, IpcKernel, @@ -1185,14 +1169,6 @@ impl fmt::Display for MachError { } } -impl StdError for MachError {} - -impl From for bincode::Error { - fn from(mach_error: MachError) -> Self { - io::Error::from(mach_error).into() - } -} - impl From for MachError { fn from(code: mach_msg_return_t) -> MachError { match code { @@ -1240,27 +1216,23 @@ impl From for MachError { } } -impl From for MachError { - fn from(kernel_error: KernelError) -> MachError { - MachError::Kernel(kernel_error) - } -} - -impl From for ipc::TryRecvError { +impl From for crate::TryRecvError { fn from(error: MachError) -> Self { match error { - MachError::NotifyNoSenders => ipc::TryRecvError::IpcError(ipc::IpcError::Disconnected), - MachError::RcvTimedOut => ipc::TryRecvError::Empty, - e => ipc::TryRecvError::IpcError(ipc::IpcError::Io(io::Error::from(e))), + MachError::NotifyNoSenders => { + crate::TryRecvError::IpcError(crate::IpcError::Disconnected) + }, + MachError::RcvTimedOut => crate::TryRecvError::Empty, + e => crate::TryRecvError::IpcError(crate::IpcError::Io(io::Error::from(e))), } } } -impl From for ipc::IpcError { +impl From for crate::IpcError { fn from(error: MachError) -> Self { match error { - MachError::NotifyNoSenders => ipc::IpcError::Disconnected, - e => ipc::IpcError::Io(io::Error::from(e)), + MachError::NotifyNoSenders => crate::IpcError::Disconnected, + e => crate::IpcError::Io(io::Error::from(e)), } } } diff --git a/src/platform/unix/mod.rs b/src/platform/unix/mod.rs index c7821366..76d04470 100644 --- a/src/platform/unix/mod.rs +++ b/src/platform/unix/mod.rs @@ -7,8 +7,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::ipc::{self, IpcMessage}; -use bincode; +use crate::ipc::IpcMessage; use fnv::FnvHasher; use libc::{ self, cmsghdr, linger, CMSG_DATA, CMSG_LEN, CMSG_SPACE, MAP_FAILED, MAP_SHARED, PROT_READ, @@ -24,7 +23,6 @@ use std::cell::Cell; use std::cmp; use std::collections::HashMap; use std::convert::TryInto; -use std::error::Error as StdError; use std::ffi::{c_uint, CString}; use std::fmt::{self, Debug, Formatter}; use std::hash::BuildHasherDefault; @@ -40,6 +38,7 @@ use std::sync::{Arc, LazyLock}; use std::thread; use std::time::{Duration, UNIX_EPOCH}; use tempfile::{Builder, TempDir}; +use thiserror::Error; const MAX_FDS_IN_CMSG: u32 = 64; @@ -906,7 +905,7 @@ impl OsIpcSharedMemory { } } -#[derive(Debug)] +#[derive(Debug, Error)] pub enum UnixError { Errno(c_int), ChannelClosed, @@ -924,6 +923,15 @@ impl UnixError { } } +impl From for crate::IpcError { + fn from(error: UnixError) -> Self { + match error { + UnixError::ChannelClosed => crate::IpcError::Disconnected, + e => crate::IpcError::Io(io::Error::from(e)), + } + } +} + impl fmt::Display for UnixError { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { match self { @@ -936,14 +944,6 @@ impl fmt::Display for UnixError { } } -impl StdError for UnixError {} - -impl From for bincode::Error { - fn from(unix_error: UnixError) -> Self { - io::Error::from(unix_error).into() - } -} - impl From for io::Error { fn from(unix_error: UnixError) -> io::Error { match unix_error { @@ -954,23 +954,16 @@ impl From for io::Error { } } -impl From for ipc::IpcError { - fn from(error: UnixError) -> Self { - match error { - UnixError::ChannelClosed => ipc::IpcError::Disconnected, - e => ipc::IpcError::Io(io::Error::from(e)), - } - } -} - -impl From for ipc::TryRecvError { +impl From for crate::TryRecvError { fn from(error: UnixError) -> Self { match error { - UnixError::ChannelClosed => ipc::TryRecvError::IpcError(ipc::IpcError::Disconnected), + UnixError::ChannelClosed => { + crate::TryRecvError::IpcError(crate::IpcError::Disconnected) + }, UnixError::Errno(code) if code == EAGAIN || code == EWOULDBLOCK => { - ipc::TryRecvError::Empty + crate::TryRecvError::Empty }, - e => ipc::TryRecvError::IpcError(ipc::IpcError::Io(io::Error::from(e))), + e => crate::TryRecvError::IpcError(crate::IpcError::Io(io::Error::from(e))), } } } diff --git a/src/platform/windows/mod.rs b/src/platform/windows/mod.rs index 2bbbff0b..1dc5d544 100644 --- a/src/platform/windows/mod.rs +++ b/src/platform/windows/mod.rs @@ -7,9 +7,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::ipc::{self, IpcMessage}; +use crate::ipc::IpcMessage; use bincode; use serde; +use thiserror::Error; use std::{ cell::{Cell, RefCell}, @@ -1954,10 +1955,13 @@ impl OsOpaqueIpcChannel { } } -#[derive(Debug)] +#[derive(Debug, Error)] pub enum WinIpcError { - WinError(WinError), + #[error("Windows Error {0}")] + WinError(#[from] WinError), + #[error("Channel Closed")] ChannelClosed, + #[error("No Data")] NoData, } @@ -1967,33 +1971,23 @@ impl WinIpcError { } } -impl From for bincode::Error { - fn from(error: WinIpcError) -> bincode::Error { - io::Error::from(error).into() - } -} - -impl From for WinIpcError { - fn from(e: WinError) -> Self { - Self::WinError(e) - } -} - -impl From for ipc::IpcError { +impl From for crate::IpcError { fn from(error: WinIpcError) -> Self { match error { - WinIpcError::ChannelClosed => ipc::IpcError::Disconnected, - e => ipc::IpcError::Io(io::Error::from(e)), + WinIpcError::ChannelClosed => crate::IpcError::Disconnected, + e => crate::IpcError::Io(io::Error::from(e)), } } } -impl From for ipc::TryRecvError { +impl From for crate::TryRecvError { fn from(error: WinIpcError) -> Self { match error { - WinIpcError::ChannelClosed => ipc::TryRecvError::IpcError(ipc::IpcError::Disconnected), - WinIpcError::NoData => ipc::TryRecvError::Empty, - e => ipc::TryRecvError::IpcError(ipc::IpcError::Io(io::Error::from(e))), + WinIpcError::ChannelClosed => { + crate::TryRecvError::IpcError(crate::IpcError::Disconnected) + }, + WinIpcError::NoData => crate::TryRecvError::Empty, + e => crate::TryRecvError::IpcError(crate::IpcError::Io(io::Error::from(e))), } } } diff --git a/src/router.rs b/src/router.rs index 45e7f9d9..36d3246b 100644 --- a/src/router.rs +++ b/src/router.rs @@ -17,6 +17,7 @@ use std::collections::HashMap; use std::sync::{LazyLock, Mutex}; use std::thread; +use crate::error::SerializationError; use crate::ipc::OpaqueIpcReceiver; use crate::ipc::{self, IpcMessage, IpcReceiver, IpcReceiverSet, IpcSelectionResult, IpcSender}; use crossbeam_channel::{self, Receiver, Sender}; @@ -240,4 +241,4 @@ enum RouterMsg { pub type RouterHandler = Box; /// Like [RouterHandler] but includes the type that will be passed to the callback -pub type TypedRouterHandler = Box) + Send>; +pub type TypedRouterHandler = Box) + Send>; diff --git a/src/test.rs b/src/test.rs index 4f4f3e0a..6188838d 100644 --- a/src/test.rs +++ b/src/test.rs @@ -16,7 +16,6 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer}; use std::cell::RefCell; #[cfg(not(any(feature = "force-inprocess", target_os = "android", target_os = "ios")))] use std::env; -use std::iter; #[cfg(not(any(feature = "force-inprocess", target_os = "android", target_os = "ios",)))] use std::process::{self, Command, Stdio}; #[cfg(not(any( @@ -130,7 +129,7 @@ fn simple() { assert_eq!(person, received_person); drop(tx); match rx.recv().unwrap_err() { - ipc::IpcError::Disconnected => (), + crate::IpcError::Disconnected => (), e => panic!("expected disconnected error, got {e:?}"), } } @@ -549,19 +548,19 @@ fn try_recv() { let person = ("Patrick Walton".to_owned(), 29); let (tx, rx) = ipc::channel().unwrap(); match rx.try_recv() { - Err(ipc::TryRecvError::Empty) => (), + Err(crate::TryRecvError::Empty) => (), v => panic!("Expected empty channel err: {v:?}"), } tx.send(person.clone()).unwrap(); let received_person = rx.try_recv().unwrap(); assert_eq!(person, received_person); match rx.try_recv() { - Err(ipc::TryRecvError::Empty) => (), + Err(crate::TryRecvError::Empty) => (), v => panic!("Expected empty channel err: {v:?}"), } drop(tx); match rx.try_recv() { - Err(ipc::TryRecvError::IpcError(ipc::IpcError::Disconnected)) => (), + Err(crate::TryRecvError::IpcError(crate::IpcError::Disconnected)) => (), v => panic!("Expected disconnected err: {v:?}"), } } @@ -573,7 +572,7 @@ fn try_recv_timeout() { let timeout = Duration::from_millis(1000); let start_recv = Instant::now(); match rx.try_recv_timeout(timeout) { - Err(ipc::TryRecvError::Empty) => { + Err(crate::TryRecvError::Empty) => { assert!(start_recv.elapsed() >= Duration::from_millis(500)) }, v => panic!("Expected empty channel err: {v:?}"), @@ -585,14 +584,14 @@ fn try_recv_timeout() { assert_eq!(person, received_person); let start_recv = Instant::now(); match rx.try_recv_timeout(timeout) { - Err(ipc::TryRecvError::Empty) => { + Err(crate::TryRecvError::Empty) => { assert!(start_recv.elapsed() >= Duration::from_millis(500)) }, v => panic!("Expected empty channel err: {v:?}"), } drop(tx); match rx.try_recv_timeout(timeout) { - Err(ipc::TryRecvError::IpcError(ipc::IpcError::Disconnected)) => (), + Err(crate::TryRecvError::IpcError(crate::IpcError::Disconnected)) => (), v => panic!("Expected disconnected err: {v:?}"), } }