-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
signal: use eventfd instead of UnixStream for signal notification #7845
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
Open
winter-loo
wants to merge
12
commits into
tokio-rs:master
Choose a base branch
from
winter-loo:eventfd_over_unixstream
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 3 commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
60142c5
signal: use eventfd instead of UnixStream for signal notification
winter-loo f7cbb0a
fix compilation on non Linux platform
winter-loo 76f49b8
use &mut self for read
winter-loo af29bd6
separate implementation
winter-loo 9a36bea
propagate low level io error
winter-loo 3b62b56
try to fix for Windows
winter-loo da7a4f1
fix code format
winter-loo b48c950
fix use std::io
winter-loo 55221b8
Merge branch 'master' into eventfd_over_unixstream
winter-loo e7e66d0
remove unused import
winter-loo 5d05e27
propagate errros instead of panic
winter-loo 0fc1242
fix Windows compilation
winter-loo File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -12,8 +12,7 @@ use crate::signal::registry::{globals, EventId, EventInfo, Globals, Storage}; | |
| use crate::signal::RxFuture; | ||
| use crate::sync::watch; | ||
|
|
||
| use mio::net::UnixStream; | ||
| use std::io::{self, Error, ErrorKind, Write}; | ||
| use std::io::{self, Error, ErrorKind}; | ||
| use std::sync::atomic::{AtomicBool, Ordering}; | ||
| use std::sync::Once; | ||
| use std::task::{Context, Poll}; | ||
|
|
@@ -61,20 +60,211 @@ impl Storage for OsStorage { | |
| } | ||
| } | ||
|
|
||
| #[cfg(any(target_os = "linux", target_os = "illumos"))] | ||
| pub(crate) mod pipe { | ||
| use std::{ | ||
| io, | ||
| os::fd::{AsRawFd, FromRawFd, OwnedFd}, | ||
| }; | ||
|
|
||
| use mio::{event, unix::SourceFd}; | ||
|
|
||
| #[derive(Debug)] | ||
| pub(crate) struct Sender { | ||
| fd: OwnedFd, | ||
| } | ||
|
|
||
| #[derive(Debug)] | ||
| pub(crate) struct Receiver { | ||
| fd: OwnedFd, | ||
| } | ||
|
|
||
| impl event::Source for Receiver { | ||
| fn register( | ||
| &mut self, | ||
| registry: &mio::Registry, | ||
| token: mio::Token, | ||
| interests: mio::Interest, | ||
| ) -> io::Result<()> { | ||
| SourceFd(&self.fd.as_raw_fd()).register(registry, token, interests) | ||
| } | ||
|
|
||
| fn reregister( | ||
| &mut self, | ||
| registry: &mio::Registry, | ||
| token: mio::Token, | ||
| interests: mio::Interest, | ||
| ) -> io::Result<()> { | ||
| SourceFd(&self.fd.as_raw_fd()).reregister(registry, token, interests) | ||
| } | ||
|
|
||
| fn deregister(&mut self, registry: &mio::Registry) -> io::Result<()> { | ||
| SourceFd(&self.fd.as_raw_fd()).deregister(registry) | ||
| } | ||
| } | ||
|
|
||
| impl Sender { | ||
| pub(crate) fn new() -> Self { | ||
| let fd = unsafe { libc::eventfd(0, libc::EFD_NONBLOCK | libc::EFD_CLOEXEC) }; | ||
| if fd < 0 { | ||
| panic!("eventfd failed: {}", io::Error::last_os_error()); | ||
| } | ||
|
||
| Sender { | ||
| fd: unsafe { OwnedFd::from_raw_fd(fd) }, | ||
| } | ||
| } | ||
|
|
||
| pub(crate) fn receiver(&self) -> Receiver { | ||
| Receiver { | ||
| fd: self.fd.try_clone().unwrap(), | ||
ipetkov marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
| } | ||
| } | ||
|
|
||
| impl Sender { | ||
| pub(crate) fn write(&self) { | ||
| unsafe { | ||
| libc::eventfd_write(self.fd.as_raw_fd(), 1); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| impl Receiver { | ||
| pub(crate) fn read(&mut self) -> libc::c_int { | ||
| let fd = &self.fd; | ||
| let mut value: libc::eventfd_t = 0; | ||
|
|
||
| unsafe { libc::eventfd_read(fd.as_raw_fd(), &mut value as *mut libc::eventfd_t) } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| #[cfg(not(any(target_os = "linux", target_os = "illumos")))] | ||
| pub(crate) mod pipe { | ||
| use mio::net::UnixStream; | ||
| use std::io::{self, Read, Write}; | ||
| use std::mem::ManuallyDrop; | ||
| use std::os::unix::io::{AsRawFd, FromRawFd}; | ||
|
|
||
| #[derive(Debug)] | ||
| pub(crate) struct Sender { | ||
| inner: UnixStream, | ||
| } | ||
|
|
||
| #[derive(Debug)] | ||
| pub(crate) struct Receiver { | ||
| inner: UnixStream, | ||
| } | ||
|
|
||
| impl Clone for Receiver { | ||
| fn clone(&self) -> Self { | ||
| let receiver_fd = self.inner.as_raw_fd(); | ||
| let original = ManuallyDrop::new(unsafe { | ||
| std::os::unix::net::UnixStream::from_raw_fd(receiver_fd) | ||
| }); | ||
| let inner = | ||
| UnixStream::from_std(original.try_clone().expect("failed to clone UnixStream")); | ||
|
||
| Self { inner } | ||
| } | ||
| } | ||
|
|
||
| impl mio::event::Source for Receiver { | ||
| fn register( | ||
| &mut self, | ||
| registry: &mio::Registry, | ||
| token: mio::Token, | ||
| interests: mio::Interest, | ||
| ) -> io::Result<()> { | ||
| self.inner.register(registry, token, interests) | ||
| } | ||
|
|
||
| fn reregister( | ||
| &mut self, | ||
| registry: &mio::Registry, | ||
| token: mio::Token, | ||
| interests: mio::Interest, | ||
| ) -> io::Result<()> { | ||
| self.inner.reregister(registry, token, interests) | ||
| } | ||
|
|
||
| fn deregister(&mut self, registry: &mio::Registry) -> io::Result<()> { | ||
| self.inner.deregister(registry) | ||
| } | ||
| } | ||
|
|
||
| impl Sender { | ||
| pub(crate) fn write(&self) { | ||
| let _ = (&self.inner).write(&[1]); | ||
| } | ||
| } | ||
|
|
||
| impl Receiver { | ||
| pub(crate) fn read(&mut self) -> libc::c_int { | ||
| // Drain the pipe completely so we can receive a new readiness event | ||
| // if another signal has come in. | ||
| let mut buf = [0; 128]; | ||
| #[allow(clippy::unused_io_amount)] | ||
| loop { | ||
| match self.inner.read(&mut buf) { | ||
| Ok(0) => panic!("EOF on self-pipe"), | ||
| Ok(_) => continue, // Keep reading | ||
| Err(e) if e.kind() == std::io::ErrorKind::WouldBlock => break, | ||
| Err(e) => panic!("Bad read on self-pipe: {e}"), | ||
ipetkov marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
| } | ||
| 0 | ||
| } | ||
| } | ||
|
|
||
| pub(crate) fn channel() -> (Sender, Receiver) { | ||
| let (sender, receiver) = UnixStream::pair().expect("failed to create UnixStream"); | ||
ipetkov marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| (Sender { inner: sender }, Receiver { inner: receiver }) | ||
| } | ||
| } | ||
|
|
||
| #[cfg(any(target_os = "linux", target_os = "illumos"))] | ||
| #[derive(Debug)] | ||
| pub(crate) struct OsExtraData { | ||
| sender: UnixStream, | ||
| pub(crate) receiver: UnixStream, | ||
| sender: pipe::Sender, | ||
| } | ||
|
|
||
| #[cfg(any(target_os = "linux", target_os = "illumos"))] | ||
| impl Default for OsExtraData { | ||
| fn default() -> Self { | ||
| let (receiver, sender) = UnixStream::pair().expect("failed to create UnixStream"); | ||
| let sender = pipe::Sender::new(); | ||
| Self { sender } | ||
| } | ||
| } | ||
|
|
||
| #[cfg(any(target_os = "linux", target_os = "illumos"))] | ||
| impl OsExtraData { | ||
| pub(crate) fn receiver(&self) -> pipe::Receiver { | ||
| self.sender.receiver() | ||
| } | ||
| } | ||
|
|
||
| #[cfg(not(any(target_os = "linux", target_os = "illumos")))] | ||
| #[derive(Debug)] | ||
| pub(crate) struct OsExtraData { | ||
| sender: pipe::Sender, | ||
| receiver: pipe::Receiver, | ||
| } | ||
ipetkov marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| #[cfg(not(any(target_os = "linux", target_os = "illumos")))] | ||
| impl Default for OsExtraData { | ||
| fn default() -> Self { | ||
| let (sender, receiver) = pipe::channel(); | ||
| Self { sender, receiver } | ||
| } | ||
| } | ||
|
|
||
| #[cfg(not(any(target_os = "linux", target_os = "illumos")))] | ||
| impl OsExtraData { | ||
| pub(crate) fn receiver(&self) -> pipe::Receiver { | ||
| self.receiver.clone() | ||
| } | ||
| } | ||
|
|
||
| /// Represents the specific kind of signal to listen for. | ||
| #[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)] | ||
| pub struct SignalKind(libc::c_int); | ||
|
|
@@ -268,8 +458,7 @@ fn action(globals: &'static Globals, signal: libc::c_int) { | |
|
|
||
| // Send a wakeup, ignore any errors (anything reasonably possible is | ||
| // full pipe and then it will wake up anyway). | ||
| let mut sender = &globals.sender; | ||
| drop(sender.write(&[1])); | ||
| globals.sender.write(); | ||
| } | ||
|
|
||
| /// Enables this module to receive signal notifications for the `signal` | ||
|
|
||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.