Skip to content

Commit

Permalink
Merge pull request #149 from vorner/stray-pending
Browse files Browse the repository at this point in the history
Deal with stray `Pending` due to race condition
  • Loading branch information
vorner authored Jul 18, 2023
2 parents 719b145 + c6623ce commit dd318c4
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 11 deletions.
2 changes: 1 addition & 1 deletion src/iterator/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,7 @@ impl<SD, E: Exfiltrator> SignalIterator<SD, E> {
/// [`PollResult::Pending`] and assume it will be called again at a later point in time.
/// The callback may be called any number of times by this function.
///
/// If the iterator was closed by the [`close`][Handle::close] method of the associtated
/// If the iterator was closed by the [`close`][Handle::close] method of the associated
/// [`Handle`] this method will return [`PollResult::Closed`].
pub fn poll_signal<R, F>(&mut self, has_signals: &mut F) -> PollResult<E::Output>
where
Expand Down
23 changes: 13 additions & 10 deletions src/iterator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,16 +302,19 @@ impl<'a, E: Exfiltrator> Iterator for Forever<'a, E> {
type Item = E::Output;

fn next(&mut self) -> Option<E::Output> {
match self.0.poll_signal(&mut SignalsInfo::<E>::has_signals) {
PollResult::Signal(result) => Some(result),
PollResult::Closed => None,
PollResult::Pending => unreachable!(
"Because of the blocking has_signals method the \
poll_signal method never returns Poll::Pending but blocks until a signal arrived"
),
// Users can't manipulate the internal file descriptors and the way we use them
// shouldn't produce any errors. So it is OK to panic.
PollResult::Err(error) => panic!("Unexpected error: {}", error),
loop {
match self.0.poll_signal(&mut SignalsInfo::<E>::has_signals) {
PollResult::Signal(result) => break Some(result),
PollResult::Closed => break None,
// In theory, the poll_signal should not return PollResult::Pending. Nevertheless,
// there's a race condition - if the other side closes the pipe/socket after
// checking for it being closed, then the `read` there returns 0 as EOF. That
// appears as pending here. Next time we should get Closed.
PollResult::Pending => continue,
// Users can't manipulate the internal file descriptors and the way we use them
// shouldn't produce any errors. So it is OK to panic.
PollResult::Err(error) => panic!("Unexpected error: {}", error),
}
}
}
}
Expand Down

0 comments on commit dd318c4

Please sign in to comment.