Skip to content

Commit 3f0752a

Browse files
committed
Unify error handling to have IpcError and TryRecvError be the main error
types. These types will give the Bincode error, Io errors (which are converted from platform errors) and Disconnect. Additionally we now use the thiserror crate which removes some of the code. Signed-off-by: Narfinger <[email protected]>
1 parent d918d57 commit 3f0752a

File tree

10 files changed

+89
-176
lines changed

10 files changed

+89
-176
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ futures-channel = { version = "0.3.31", optional = true }
3838
futures-core = { version = "0.3.31", optional = true }
3939
libc = "0.2.162"
4040
serde = { version = "1.0", features = ["rc"] }
41+
thiserror = "2.0.12"
4142
uuid = { version = "1", features = ["v4"] }
4243

4344
[target.'cfg(any(target_os = "linux", target_os = "openbsd", target_os = "freebsd", target_os = "illumos"))'.dependencies]

src/error.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
use std::io;
2+
3+
use thiserror::Error;
4+
5+
#[cfg(all(
6+
not(feature = "force-inprocess"),
7+
any(
8+
target_os = "linux",
9+
target_os = "openbsd",
10+
target_os = "freebsd",
11+
target_os = "illumos",
12+
)
13+
))]
14+
#[derive(Debug, Error)]
15+
pub enum IpcError {
16+
#[error("Error in decoding or encoding: {0}")]
17+
Bincode(#[from] bincode::Error),
18+
#[error("Error in IO: {0}")]
19+
Io(#[from] io::Error),
20+
#[error("Ipc Disconnected")]
21+
Disconnected,
22+
}
23+
24+
#[derive(Debug, Error)]
25+
pub enum TryRecvError {
26+
#[error("IPC error")]
27+
IpcError(#[from] IpcError),
28+
#[error("Channel empty")]
29+
Empty,
30+
}

src/ipc.rs

Lines changed: 8 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ use crate::platform::{self, OsIpcChannel, OsIpcReceiver, OsIpcReceiverSet, OsIpc
1111
use crate::platform::{
1212
OsIpcOneShotServer, OsIpcSelectionResult, OsIpcSharedMemory, OsOpaqueIpcChannel,
1313
};
14+
use crate::{IpcError, TryRecvError};
1415

1516
use bincode;
1617
use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer};
1718
use std::cell::RefCell;
1819
use std::cmp::min;
19-
use std::error::Error as StdError;
2020
use std::fmt::{self, Debug, Formatter};
2121
use std::io;
2222
use std::marker::PhantomData;
@@ -37,57 +37,6 @@ thread_local! {
3737
const { RefCell::new(Vec::new()) }
3838
}
3939

40-
#[derive(Debug)]
41-
pub enum IpcError {
42-
Bincode(bincode::Error),
43-
Io(io::Error),
44-
Disconnected,
45-
}
46-
47-
impl fmt::Display for IpcError {
48-
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
49-
match *self {
50-
IpcError::Bincode(ref err) => write!(fmt, "bincode error: {err}"),
51-
IpcError::Io(ref err) => write!(fmt, "io error: {err}"),
52-
IpcError::Disconnected => write!(fmt, "disconnected"),
53-
}
54-
}
55-
}
56-
57-
impl StdError for IpcError {
58-
fn source(&self) -> Option<&(dyn StdError + 'static)> {
59-
match *self {
60-
IpcError::Bincode(ref err) => Some(err),
61-
IpcError::Io(ref err) => Some(err),
62-
IpcError::Disconnected => None,
63-
}
64-
}
65-
}
66-
67-
#[derive(Debug)]
68-
pub enum TryRecvError {
69-
IpcError(IpcError),
70-
Empty,
71-
}
72-
73-
impl fmt::Display for TryRecvError {
74-
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
75-
match *self {
76-
TryRecvError::IpcError(ref err) => write!(fmt, "ipc error: {err}"),
77-
TryRecvError::Empty => write!(fmt, "empty"),
78-
}
79-
}
80-
}
81-
82-
impl StdError for TryRecvError {
83-
fn source(&self) -> Option<&(dyn StdError + 'static)> {
84-
match *self {
85-
TryRecvError::IpcError(ref err) => Some(err),
86-
TryRecvError::Empty => None,
87-
}
88-
}
89-
}
90-
9140
/// Create a connected [IpcSender] and [IpcReceiver] that
9241
/// transfer messages of a given type provided by type `T`
9342
/// or inferred by the types of messages sent by the sender.
@@ -248,16 +197,12 @@ where
248197
{
249198
/// Blocking receive.
250199
pub fn recv(&self) -> Result<T, IpcError> {
251-
self.os_receiver.recv()?.to().map_err(IpcError::Bincode)
200+
self.os_receiver.recv()?.to()
252201
}
253202

254203
/// Non-blocking receive
255204
pub fn try_recv(&self) -> Result<T, TryRecvError> {
256-
self.os_receiver
257-
.try_recv()?
258-
.to()
259-
.map_err(IpcError::Bincode)
260-
.map_err(TryRecvError::IpcError)
205+
self.os_receiver.try_recv()?.to().map_err(|e| e.into())
261206
}
262207

263208
/// Blocks for up to the specified duration attempting to receive a message.
@@ -270,8 +215,7 @@ where
270215
self.os_receiver
271216
.try_recv_timeout(duration)?
272217
.to()
273-
.map_err(IpcError::Bincode)
274-
.map_err(TryRecvError::IpcError)
218+
.map_err(|e| e.into())
275219
}
276220

277221
/// Erase the type of the channel.
@@ -364,7 +308,7 @@ where
364308
}
365309

366310
/// Send data across the channel to the receiver.
367-
pub fn send(&self, data: T) -> Result<(), bincode::Error> {
311+
pub fn send(&self, data: T) -> Result<(), IpcError> {
368312
let mut bytes = Vec::with_capacity(4096);
369313
OS_IPC_CHANNELS_FOR_SERIALIZATION.with(|os_ipc_channels_for_serialization| {
370314
OS_IPC_SHARED_MEMORY_REGIONS_FOR_SERIALIZATION.with(
@@ -726,7 +670,7 @@ impl IpcMessage {
726670
}
727671

728672
/// Deserialize the raw data in the contained message into the inferred type.
729-
pub fn to<T>(mut self) -> Result<T, bincode::Error>
673+
pub fn to<T>(mut self) -> Result<T, IpcError>
730674
where
731675
T: for<'de> Deserialize<'de> + Serialize,
732676
{
@@ -744,7 +688,7 @@ impl IpcMessage {
744688
.map(Some)
745689
.collect(),
746690
);
747-
let result = bincode::deserialize(&self.data[..]);
691+
let result = bincode::deserialize(&self.data[..]).map_err(|e| e.into());
748692
*os_ipc_shared_memory_regions_for_deserialization.borrow_mut() =
749693
old_ipc_shared_memory_regions_for_deserialization;
750694
mem::swap(
@@ -886,7 +830,7 @@ where
886830
))
887831
}
888832

889-
pub fn accept(self) -> Result<(IpcReceiver<T>, T), bincode::Error> {
833+
pub fn accept(self) -> Result<(IpcReceiver<T>, T), IpcError> {
890834
let (os_receiver, ipc_message) = self.os_server.accept()?;
891835
Ok((
892836
IpcReceiver {

src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,12 @@ pub mod asynch;
3232
#[cfg(all(not(feature = "force-inprocess"), target_os = "windows"))]
3333
extern crate windows;
3434

35+
mod error;
3536
pub mod ipc;
3637
pub mod platform;
3738
pub mod router;
3839

3940
#[cfg(test)]
4041
mod test;
4142

42-
pub use bincode::{Error, ErrorKind};
43+
pub use error::{IpcError, TryRecvError};

src/platform/inprocess/mod.rs

Lines changed: 7 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -387,11 +387,15 @@ impl OsIpcSharedMemory {
387387
}
388388
}
389389

390-
#[derive(Debug, PartialEq)]
390+
#[derive(Debug, PartialEq, Error)]
391391
pub enum ChannelError {
392+
#[error("Channel Closed")]
392393
ChannelClosedError,
394+
#[error("Broken Pipe")]
393395
BrokenPipeError,
396+
#[error("Channel Empty")]
394397
ChannelEmpty,
398+
#[error("Unknown Error")]
395399
UnknownError,
396400
}
397401

@@ -402,30 +406,11 @@ impl ChannelError {
402406
}
403407
}
404408

405-
impl fmt::Display for ChannelError {
406-
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
407-
match *self {
408-
ChannelError::ChannelClosedError => write!(fmt, "channel closed"),
409-
ChannelError::BrokenPipeError => write!(fmt, "broken pipe"),
410-
ChannelError::ChannelEmpty => write!(fmt, "channel empty"),
411-
ChannelError::UnknownError => write!(fmt, "unknown error"),
412-
}
413-
}
414-
}
415-
416-
impl StdError for ChannelError {}
417-
418-
impl From<ChannelError> for bincode::Error {
419-
fn from(crossbeam_error: ChannelError) -> Self {
420-
io::Error::from(crossbeam_error).into()
421-
}
422-
}
423-
424409
impl From<ChannelError> for ipc::IpcError {
425410
fn from(error: ChannelError) -> Self {
426411
match error {
427412
ChannelError::ChannelClosedError => ipc::IpcError::Disconnected,
428-
e => ipc::IpcError::Bincode(io::Error::from(e).into()),
413+
e => ipc::IpcError::Io(io::Error::from(e).into()),
429414
}
430415
}
431416
}
@@ -437,7 +422,7 @@ impl From<ChannelError> for ipc::TryRecvError {
437422
ipc::TryRecvError::IpcError(ipc::IpcError::Disconnected)
438423
},
439424
ChannelError::ChannelEmpty => ipc::TryRecvError::Empty,
440-
e => ipc::TryRecvError::IpcError(ipc::IpcError::Bincode(io::Error::from(e).into())),
425+
e => ipc::TryRecvError::IpcError(ipc::IpcError::Io(io::Error::from(e).into())),
441426
}
442427
}
443428
}

src/platform/macos/mod.rs

Lines changed: 12 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -997,43 +997,28 @@ impl Message {
997997
}
998998
}
999999

1000-
#[derive(Clone, Copy, Debug, PartialEq)]
1000+
#[derive(Clone, Copy, Debug, Error, PartialEq)]
10011001
pub enum KernelError {
1002+
#[error("Success")]
10021003
Success,
1004+
#[error("No room in IPC name space for another right.")]
10031005
NoSpace,
1006+
#[error("Name doesn't denote a right in the task")]
10041007
InvalidName,
1008+
#[error("Name denotes a right, but not an appropiate right.")]
10051009
InvalidRight,
1010+
#[error("Blatant range error")]
10061011
InvalidValue,
1012+
#[error("The supplied (port) capability is improper")]
10071013
InvalidCapability,
1014+
#[error("Operation would overflow limit on user-references")]
10081015
UrefsOverflow,
1016+
#[error("Receive right is not a member of a port set.")]
10091017
NotInSet,
1018+
#[error("Unkown kernel error. {0}")]
10101019
Unknown(kern_return_t),
10111020
}
10121021

1013-
impl fmt::Display for KernelError {
1014-
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1015-
match *self {
1016-
KernelError::Success => write!(fmt, "Success."),
1017-
KernelError::NoSpace => write!(fmt, "No room in IPC name space for another right."),
1018-
KernelError::InvalidName => write!(fmt, "Name doesn't denote a right in the task."),
1019-
KernelError::InvalidRight => {
1020-
write!(fmt, "Name denotes a right, but not an appropriate right.")
1021-
},
1022-
KernelError::InvalidValue => write!(fmt, "Blatant range error."),
1023-
KernelError::InvalidCapability => {
1024-
write!(fmt, "The supplied (port) capability is improper.")
1025-
},
1026-
KernelError::UrefsOverflow => {
1027-
write!(fmt, "Operation would overflow limit on user-references.")
1028-
},
1029-
KernelError::NotInSet => write!(fmt, "Receive right is not a member of a port set."),
1030-
KernelError::Unknown(code) => write!(fmt, "Unknown kernel error: {:x}", code),
1031-
}
1032-
}
1033-
}
1034-
1035-
impl StdError for KernelError {}
1036-
10371022
impl From<kern_return_t> for KernelError {
10381023
fn from(code: kern_return_t) -> KernelError {
10391024
match code {
@@ -1050,10 +1035,10 @@ impl From<kern_return_t> for KernelError {
10501035
}
10511036
}
10521037

1053-
#[derive(Clone, Copy, Debug, PartialEq)]
1038+
#[derive(Clone, Copy, Debug, Error, PartialEq)]
10541039
pub enum MachError {
10551040
Success,
1056-
Kernel(KernelError),
1041+
Kernel(#[from] KernelError),
10571042
IpcSpace,
10581043
VmSpace,
10591044
IpcKernel,
@@ -1185,14 +1170,6 @@ impl fmt::Display for MachError {
11851170
}
11861171
}
11871172

1188-
impl StdError for MachError {}
1189-
1190-
impl From<MachError> for bincode::Error {
1191-
fn from(mach_error: MachError) -> Self {
1192-
io::Error::from(mach_error).into()
1193-
}
1194-
}
1195-
11961173
impl From<mach_msg_return_t> for MachError {
11971174
fn from(code: mach_msg_return_t) -> MachError {
11981175
match code {
@@ -1240,12 +1217,6 @@ impl From<mach_msg_return_t> for MachError {
12401217
}
12411218
}
12421219

1243-
impl From<KernelError> for MachError {
1244-
fn from(kernel_error: KernelError) -> MachError {
1245-
MachError::Kernel(kernel_error)
1246-
}
1247-
}
1248-
12491220
impl From<MachError> for ipc::TryRecvError {
12501221
fn from(error: MachError) -> Self {
12511222
match error {

0 commit comments

Comments
 (0)