Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle interrupts while polling #164

Merged
merged 4 commits into from
Oct 27, 2023
Merged

Handle interrupts while polling #164

merged 4 commits into from
Oct 27, 2023

Conversation

notgull
Copy link
Member

@notgull notgull commented Oct 21, 2023

Previous, Poller::wait would bubble signal interruption error to the user. However, this may be unexpected for simple use cases. Thus, this commit makes it so, if ErrorKind::Interrupted is received by the underlying wait() call, it clears the events and tries to wait again.

This also adds a test for this interruption written by @psychon.

Closes #162

notgull and others added 2 commits October 20, 2023 17:09
Previous, `Poller::wait` would bubble signal interruption error to the user.
However, this may be unexpected for simple use cases. Thus, this commit makes
it so, if `ErrorKind::Interrupted` is received by the underlying `wait()` call,
it clears the events and tries to wait again.

This also adds a test for this interruption written by @psychon.

Co-Authored-By: Uli Schlachter <[email protected]>
Signed-off-by: John Nunley <[email protected]>
@notgull notgull requested a review from fogti October 21, 2023 01:27
@psychon
Copy link
Contributor

psychon commented Oct 21, 2023

I would claim that this mis-handles timeouts. A poll with a timeout of one second can now run infinitely long (although this is quite unlikely):

  • self.poller.wait(events, OneSecond) runs for 0.5 seconds
  • A signal arrives and interrupts the poller
  • self.poller.wait(events, OneSecond) runs for 0.5 seconds
  • A signal arrives and interrupts the poller
  • repeat indefinitely

I would propose:

diff --git a/src/lib.rs b/src/lib.rs
index 9882c8e..8078ee1 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -652,7 +652,14 @@ impl Poller {
 
         if let Ok(_lock) = self.lock.try_lock() {
             // Wait for I/O events.
-            self.poller.wait(&mut events.events, timeout)?;
+            match self.poller.wait(&mut events.events, timeout) {
+                Ok(()) => {}
+                // Turn interruption into a spurious wakeup without errors
+                Err(e) if e.kind() == io::ErrorKind::Interrupted => {
+                    events.clear();
+                },
+                Err(e) => return Err(e),
+            };
 
             // Clear the notification, if any.
             self.notified.swap(false, Ordering::SeqCst);

src/lib.rs Show resolved Hide resolved
@fogti
Copy link
Member

fogti commented Oct 21, 2023

An alternative would be to only do this if no timeout was given (because spurious/non-action wakeups need to be handled anyways when using timeouts usually)

Copy link
Member

@fogti fogti left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(timeout concerns)

Signed-off-by: John Nunley <[email protected]>
Signed-off-by: John Nunley <[email protected]>
@notgull notgull merged commit b9ab821 into master Oct 27, 2023
24 checks passed
@notgull notgull deleted the notgull/interrupt branch October 27, 2023 14:02
@notgull notgull mentioned this pull request Oct 29, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

Should this crate intercept Interrupt errors?
3 participants