diff --git a/src/platform/inprocess/mod.rs b/src/platform/inprocess/mod.rs index 8253be356..9bf0c156d 100644 --- a/src/platform/inprocess/mod.rs +++ b/src/platform/inprocess/mod.rs @@ -100,7 +100,8 @@ impl OsIpcReceiver { Ok(MpscChannelMessage(d,c,s)) => Ok((d, c.into_iter().map(OsOpaqueIpcChannel::new).collect(), s)), - Err(_) => Err(MpscError::ChannelClosedError), + Err(mpsc::TryRecvError::Disconnected) => Err(MpscError::ChannelClosedError), + Err(_) => Err(MpscError::UnknownError), } } } @@ -141,7 +142,7 @@ impl OsIpcSender { -> Result<(),MpscError> { match self.sender.borrow().send(MpscChannelMessage(data.to_vec(), ports, shared_memory_regions)) { - Err(_) => Err(MpscError::ChannelClosedError), + Err(_) => Err(MpscError::BrokenPipeError), Ok(_) => Ok(()), } } @@ -376,6 +377,7 @@ impl OsIpcSharedMemory { #[derive(Debug, PartialEq)] pub enum MpscError { ChannelClosedError, + BrokenPipeError, UnknownError, } @@ -396,7 +398,10 @@ impl From for Error { fn from(mpsc_error: MpscError) -> Error { match mpsc_error { MpscError::ChannelClosedError => { - Error::new(ErrorKind::BrokenPipe, "MPSC channel closed") + Error::new(ErrorKind::ConnectionReset, "MPSC channel sender closed") + } + MpscError::BrokenPipeError => { + Error::new(ErrorKind::BrokenPipe, "MPSC channel receiver closed") } MpscError::UnknownError => Error::new(ErrorKind::Other, "Other MPSC channel error"), } diff --git a/src/platform/test.rs b/src/platform/test.rs index a73786289..16320965b 100644 --- a/src/platform/test.rs +++ b/src/platform/test.rs @@ -699,6 +699,20 @@ fn no_senders_notification() { assert!(result.unwrap_err().channel_is_closed()); } +/// Checks that a broken pipe notification is returned by `send()` +/// after the receive end was closed. +#[test] +fn no_receiver_notification() { + let (sender, receiver) = platform::channel().unwrap(); + drop(receiver); + let data: &[u8] = b"1234567"; + let result = sender.send(data, vec![], vec![]); + assert!(result.is_err()); + // We don't have an actual method for distinguishing a "broken pipe" error -- + // but at least it's not supposed to signal the same condition as closing the sender. + assert!(!result.unwrap_err().channel_is_closed()); +} + #[test] fn shared_memory() { let (tx, rx) = platform::channel().unwrap(); @@ -730,6 +744,23 @@ fn try_recv() { assert!(rx.try_recv().is_err()); } +/// Checks that a channel closed notification is returned by `try_recv()`. +/// +/// Also checks that the "no data" notification returned by `try_recv()` +/// when no data is pending but before the channel is closed, +/// is distinguishable from the actual "channel closed" notification. +#[test] +fn no_senders_notification_try_recv() { + let (sender, receiver) = platform::channel().unwrap(); + let result = receiver.try_recv(); + assert!(result.is_err()); + assert!(!result.unwrap_err().channel_is_closed()); + drop(sender); + let result = receiver.try_recv(); + assert!(result.is_err()); + assert!(result.unwrap_err().channel_is_closed()); +} + #[test] fn try_recv_large() { let (tx, rx) = platform::channel().unwrap();