From 0cc9a8a270b044b7a6fea486f32bf49093c88f86 Mon Sep 17 00:00:00 2001 From: Thomas de Zeeuw Date: Sat, 4 Feb 2023 16:16:21 +0100 Subject: [PATCH 1/8] Disable uninlined-format-args Clippy lint Our MSRV too low to support this. --- .github/workflows/ci.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6c2775b1f..2a9a47316 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -61,6 +61,8 @@ jobs: - uses: actions-rs/toolchain@v1 with: profile: minimal + # NOTE: When updating also update Clippy flags, some are disabled due to + # MSRV. toolchain: 1.46.0 override: true - name: Check @@ -90,7 +92,8 @@ jobs: override: true components: clippy - name: Clippy - run: cargo clippy --all-targets --all-features -- -D warnings -A clippy::cognitive-complexity + # NOTE: `clippy::uninlined-format-args` is enabled due to MSRV. + run: cargo clippy --all-targets --all-features -- -D warnings -A clippy::cognitive-complexity -A clippy::uninlined-format-args Docs: runs-on: ubuntu-latest timeout-minutes: 10 From e0fcbf583b774c12ae113cc0936b961dd828364c Mon Sep 17 00:00:00 2001 From: Thomas de Zeeuw Date: Sat, 4 Feb 2023 15:57:58 +0100 Subject: [PATCH 2/8] Add test_sanitizer Makefile target Runs the tests with a sanitizer enabled. --- Makefile | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Makefile b/Makefile index 514798c93..e5316cb50 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,9 @@ # Targets available via Rustup that are supported. TARGETS ?= aarch64-apple-ios aarch64-linux-android arm-linux-androideabi i686-unknown-linux-gnu x86_64-apple-darwin x86_64-apple-ios x86_64-pc-windows-msvc x86_64-unknown-freebsd x86_64-unknown-illumos x86_64-unknown-linux-gnu x86_64-unknown-netbsd x86_64-unknown-redox +# Example value: `nightly-x86_64-apple-darwin`. +RUSTUP_TOOLCHAIN ?= $(shell rustup show active-toolchain | cut -d' ' -f1) +# Architecture target. Example value: `x86_64-apple-darwin`. +RUSTUP_TARGET ?= $(shell echo $(RUSTUP_TOOLCHAIN) | cut -d'-' -f2,3,4,5) test: cargo test --all-features @@ -10,6 +14,15 @@ test_all: check_all_targets cargo hack test --feature-powerset cargo hack test --feature-powerset --release +# NOTE: Requires a nightly compiler. +# NOTE: Keep `RUSTFLAGS` and `RUSTDOCFLAGS` in sync to ensure the doc tests +# compile correctly. +test_sanitizer: + @if [ -z $${SAN+x} ]; then echo "Required '\$$SAN' variable is not set" 1>&2; exit 1; fi + RUSTFLAGS="-Z sanitizer=$$SAN -Z sanitizer-memory-track-origins" \ + RUSTDOCFLAGS="-Z sanitizer=$$SAN -Z sanitizer-memory-track-origins" \ + cargo test -Z build-std --all-features --target $(RUSTUP_TARGET) + # Check all targets using all features. check_all_targets: $(TARGETS) $(TARGETS): From 132fd1848f28f1f45291d213c476ea89f29b5e9a Mon Sep 17 00:00:00 2001 From: Thomas de Zeeuw Date: Sat, 4 Feb 2023 15:58:58 +0100 Subject: [PATCH 3/8] Enable testing with sanitizers on the CI --- .github/workflows/ci.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2a9a47316..07dde910f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -139,6 +139,24 @@ jobs: run: cargo install --debug cargo-hack - name: Check all targets run: make check_all_targets + Sanitizer: + runs-on: ubuntu-latest + timeout-minutes: 10 + strategy: + fail-fast: false + matrix: + sanitizer: [address, leak, memory, thread] + steps: + - uses: actions/checkout@v2 + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: nightly + override: true + - name: Add rust source + run: rustup component add rust-src + - name: Run tests with sanitizer + run: make test_sanitizer SAN=${{ matrix.sanitizer }} # Single job required to merge the pr. Passed: runs-on: ubuntu-latest From 7ab77669fa97675c878948a1de70110e9b835fe6 Mon Sep 17 00:00:00 2001 From: Thomas de Zeeuw Date: Sat, 4 Feb 2023 16:10:48 +0100 Subject: [PATCH 4/8] Drop support for v0.6 --- .github/workflows/ci.yml | 4 ++-- README.md | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 07dde910f..77c19929c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,9 +1,9 @@ name: CI on: push: - branches: [ "master", "v0.6.x", "v0.7.x" ] + branches: [ "master", "v0.7.x" ] pull_request: - branches: [ "master", "v0.6.x", "v0.7.x" ] + branches: [ "master", "v0.7.x" ] env: CARGO_TERM_COLOR: always RUST_BACKTRACE: full diff --git a/README.md b/README.md index c17f3d3ed..d5b60f9a4 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,6 @@ overhead as possible over the OS abstractions. * [master](https://tokio-rs.github.io/mio/doc/mio/) * [v0.8](https://docs.rs/mio/^0.8) * [v0.7](https://docs.rs/mio/^0.7) -* [v0.6](https://docs.rs/mio/^0.6) This is a low level library, if you are looking for something easier to get started with, see [Tokio](https://tokio.rs). From 2c8396d4f461055ff7ffbb44d0ac83424357f634 Mon Sep 17 00:00:00 2001 From: Alex Touchet Date: Sun, 5 Feb 2023 10:12:49 -0800 Subject: [PATCH 5/8] Make spelling of "I/O" consistent --- Cargo.toml | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index dc037dcfe..d146e1705 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ authors = [ "Thomas de Zeeuw ", "Tokio Contributors ", ] -description = "Lightweight non-blocking IO" +description = "Lightweight non-blocking I/O." homepage = "https://github.com/tokio-rs/mio" repository = "https://github.com/tokio-rs/mio" readme = "README.md" diff --git a/README.md b/README.md index d5b60f9a4..d2dcebc96 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Mio – Metal IO +# Mio – Metal I/O Mio is a fast, low-level I/O library for Rust focusing on non-blocking APIs and event notification for building high performance I/O apps with as little From 35a44b67f272ae521947766830d3c2b9872835db Mon Sep 17 00:00:00 2001 From: Constantin Nickel Date: Mon, 6 Feb 2023 12:13:08 +0100 Subject: [PATCH 6/8] Replace unmaintained/outdated GitHub Actions The toolchain is now installed `dtolnay/rust-toolchain`. --- .github/workflows/ci.yml | 67 +++++++++++----------------------------- 1 file changed, 18 insertions(+), 49 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 77c19929c..731deeb62 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,12 +21,8 @@ jobs: matrix: os: ["ubuntu-latest", "macos-latest", "windows-latest"] steps: - - uses: actions/checkout@v2 - - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - override: true + - uses: actions/checkout@v3 + - uses: dtolnay/rust-toolchain@stable - name: Install Cargo-hack run: cargo install --debug cargo-hack - name: Check all features @@ -43,12 +39,8 @@ jobs: matrix: os: ["ubuntu-latest", "macos-latest", "windows-latest"] steps: - - uses: actions/checkout@v2 - - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: nightly - override: true + - uses: actions/checkout@v3 + - uses: dtolnay/rust-toolchain@nightly - name: Install minimal verions run: cargo update -Zminimal-versions - name: Tests @@ -57,14 +49,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 10 steps: - - uses: actions/checkout@v2 - - uses: actions-rs/toolchain@v1 + - uses: actions/checkout@v3 + - uses: dtolnay/rust-toolchain@master with: - profile: minimal # NOTE: When updating also update Clippy flags, some are disabled due to # MSRV. toolchain: 1.46.0 - override: true - name: Check # We only run check allowing us to use newer features in tests. run: cargo check --all-features @@ -72,24 +62,17 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 10 steps: - - uses: actions/checkout@v2 - - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: nightly - override: true + - uses: actions/checkout@v3 + - uses: dtolnay/rust-toolchain@nightly - name: Tests run: cargo test --all-features Clippy: runs-on: ubuntu-latest timeout-minutes: 10 steps: - - uses: actions/checkout@v2 - - uses: actions-rs/toolchain@v1 + - uses: actions/checkout@v3 + - uses: dtolnay/rust-toolchain@stable with: - profile: minimal - toolchain: stable - override: true components: clippy - name: Clippy # NOTE: `clippy::uninlined-format-args` is enabled due to MSRV. @@ -98,24 +81,17 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 10 steps: - - uses: actions/checkout@v2 - - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - override: true + - uses: actions/checkout@v3 + - uses: dtolnay/rust-toolchain@stable - name: Check docs run: RUSTDOCFLAGS="-D warnings" cargo doc --no-deps --all-features Rustfmt: runs-on: ubuntu-latest timeout-minutes: 10 steps: - - uses: actions/checkout@v2 - - uses: actions-rs/toolchain@v1 + - uses: actions/checkout@v3 + - uses: dtolnay/rust-toolchain@stable with: - profile: minimal - toolchain: stable - override: true components: rustfmt - name: Check formatting # FIXME: for some reason this doesn't actually check all files. @@ -126,12 +102,9 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 10 steps: - - uses: actions/checkout@v2 - - uses: actions-rs/toolchain@v1 + - uses: actions/checkout@v3 + - uses: dtolnay/rust-toolchain@stable with: - profile: minimal - toolchain: stable - override: true components: clippy - name: Install all targets run: make install_targets @@ -147,12 +120,8 @@ jobs: matrix: sanitizer: [address, leak, memory, thread] steps: - - uses: actions/checkout@v2 - - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: nightly - override: true + - uses: actions/checkout@v3 + - uses: dtolnay/rust-toolchain@nightly - name: Add rust source run: rustup component add rust-src - name: Run tests with sanitizer From 691112dc97a3f2cbe2e0e97a6c1f919c21dc7cab Mon Sep 17 00:00:00 2001 From: Thomas de Zeeuw Date: Tue, 7 Feb 2023 11:24:45 +0100 Subject: [PATCH 7/8] Remove outdated doc link --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index d2dcebc96..bebd2af71 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,6 @@ overhead as possible over the OS abstractions. **API documentation** -* [master](https://tokio-rs.github.io/mio/doc/mio/) * [v0.8](https://docs.rs/mio/^0.8) * [v0.7](https://docs.rs/mio/^0.7) From ba1e1964be2caed46ba8a9e9bf5718677f5949ce Mon Sep 17 00:00:00 2001 From: Thomas de Zeeuw Date: Sat, 4 Feb 2023 15:38:58 +0100 Subject: [PATCH 8/8] Add Interest::PRIORITY To trigger Event::is_priority on Linux and Android. In the future we might want to include EV_OOBAND for kqueue, but that seems to be Apple only (FreeBSD and OpenBSD don't implement it at least). Co-authored-by: Tuomas Laakkonen --- src/interest.rs | 34 ++++++++++++++--------- src/sys/unix/selector/epoll.rs | 6 ++++- tests/tcp_stream.rs | 49 ++++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 13 deletions(-) diff --git a/src/interest.rs b/src/interest.rs index 0aa0bda89..5370398e9 100644 --- a/src/interest.rs +++ b/src/interest.rs @@ -20,18 +20,9 @@ pub struct Interest(NonZeroU8); const READABLE: u8 = 0b0001; const WRITABLE: u8 = 0b0010; // The following are not available on all platforms. -#[cfg_attr( - not(any( - target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "macos" - )), - allow(dead_code) -)] const AIO: u8 = 0b0100; -#[cfg_attr(not(target_os = "freebsd"), allow(dead_code))] const LIO: u8 = 0b1000; +const PRIORITY: u8 = 0b10000; impl Interest { /// Returns a `Interest` set representing readable interests. @@ -53,6 +44,10 @@ impl Interest { #[cfg(target_os = "freebsd")] pub const LIO: Interest = Interest(unsafe { NonZeroU8::new_unchecked(LIO) }); + /// Returns a `Interest` set representing priority completion interests. + #[cfg(any(target_os = "linux", target_os = "android"))] + pub const PRIORITY: Interest = Interest(unsafe { NonZeroU8::new_unchecked(PRIORITY) }); + /// Add together two `Interest`. /// /// This does the same thing as the `BitOr` implementation, but is a @@ -104,15 +99,20 @@ impl Interest { (self.0.get() & WRITABLE) != 0 } - /// Returns true if `Interest` contains AIO readiness + /// Returns true if `Interest` contains AIO readiness. pub const fn is_aio(self) -> bool { (self.0.get() & AIO) != 0 } - /// Returns true if `Interest` contains LIO readiness + /// Returns true if `Interest` contains LIO readiness. pub const fn is_lio(self) -> bool { (self.0.get() & LIO) != 0 } + + /// Returns true if `Interest` contains priority readiness. + pub const fn is_priority(self) -> bool { + (self.0.get() & PRIORITY) != 0 + } } impl ops::BitOr for Interest { @@ -173,6 +173,16 @@ impl fmt::Debug for Interest { one = true } } + #[cfg(any(target_os = "linux", target_os = "android"))] + { + if self.is_priority() { + if one { + write!(fmt, " | ")? + } + write!(fmt, "PRIORITY")?; + one = true + } + } debug_assert!(one, "printing empty interests"); Ok(()) } diff --git a/src/sys/unix/selector/epoll.rs b/src/sys/unix/selector/epoll.rs index 8bad3830d..1809a2bb1 100644 --- a/src/sys/unix/selector/epoll.rs +++ b/src/sys/unix/selector/epoll.rs @@ -1,6 +1,6 @@ use crate::{Interest, Token}; -use libc::{EPOLLET, EPOLLIN, EPOLLOUT, EPOLLRDHUP}; +use libc::{EPOLLET, EPOLLIN, EPOLLOUT, EPOLLPRI, EPOLLRDHUP}; use log::error; use std::os::unix::io::{AsRawFd, RawFd}; #[cfg(debug_assertions)] @@ -177,6 +177,10 @@ fn interests_to_epoll(interests: Interest) -> u32 { kind |= EPOLLOUT; } + if interests.is_priority() { + kind |= EPOLLPRI; + } + kind as u32 } diff --git a/tests/tcp_stream.rs b/tests/tcp_stream.rs index a2288a173..26a5b4706 100644 --- a/tests/tcp_stream.rs +++ b/tests/tcp_stream.rs @@ -793,3 +793,52 @@ fn hup_event_on_disconnect() { vec![ExpectEvent::new(Token(1), Interest::READABLE)], ); } + +#[test] +#[cfg(any(target_os = "linux", target_os = "android"))] +fn priority_event_on_oob_data() { + let (mut poll, mut events) = init_with_poll(); + let addr: SocketAddr = "127.0.0.1:0".parse().unwrap(); + + let listener = std::net::TcpListener::bind(addr).unwrap(); + let addr = listener.local_addr().unwrap(); + + let mut client = TcpStream::connect(addr).unwrap(); + poll.registry() + .register( + &mut client, + Token(0), + Interest::READABLE | Interest::PRIORITY, + ) + .unwrap(); + + let (stream, _) = listener.accept().unwrap(); + + // Sending out of bound data should trigger priority event. + send_oob_data(&stream, DATA1).unwrap(); + expect_events( + &mut poll, + &mut events, + vec![ExpectEvent::new( + Token(0), + Readiness::READABLE | Readiness::PRIORITY, + )], + ); +} + +#[cfg(any(target_os = "linux", target_os = "android"))] +fn send_oob_data(stream: &S, data: &[u8]) -> io::Result { + unsafe { + let res = libc::send( + stream.as_raw_fd(), + data.as_ptr().cast(), + data.len(), + libc::MSG_OOB, + ); + if res == -1 { + Err(io::Error::last_os_error()) + } else { + Ok(res as usize) + } + } +}