Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fb5f596757 | ||
|
|
a053539bd8 | ||
|
|
6df2fb1abb | ||
|
|
c0d8804d87 | ||
|
|
0aed20ae81 | ||
|
|
a169a606f8 | ||
|
|
cd0423c472 | ||
|
|
fa23f6ea1a | ||
|
|
ba26c767b9 | ||
|
|
56831e931d | ||
|
|
a1de661e22 | ||
|
|
aa90e8ee2b | ||
|
|
c68cde44c5 | ||
|
|
1bb1749ddb | ||
|
|
92db541d17 | ||
|
|
1251c288ab | ||
|
|
f2c88b8750 | ||
|
|
42611b1c06 | ||
|
|
62b8ed700c | ||
|
|
453dc1e331 | ||
|
|
82468508a8 | ||
|
|
f1b580c7f4 |
@ -1,8 +1,8 @@
|
||||
freebsd_instance:
|
||||
image: freebsd-11-2-release-amd64
|
||||
image_family: freebsd-11-3-snap
|
||||
|
||||
task:
|
||||
name: FreeBSD 11.2 amd64
|
||||
name: FreeBSD
|
||||
setup_script:
|
||||
- pkg install -y curl
|
||||
- curl https://sh.rustup.rs -sSf --output rustup.sh
|
||||
@ -15,7 +15,7 @@ task:
|
||||
- cargo build --no-default-features
|
||||
test_script:
|
||||
- . $HOME/.cargo/env
|
||||
- cargo test
|
||||
- RUST_BACKTRACE=1 cargo test
|
||||
- cargo test --no-default-features
|
||||
before_cache_script:
|
||||
- rm -rf $HOME/.cargo/registry/index
|
||||
|
||||
16
CHANGELOG.md
16
CHANGELOG.md
@ -1,3 +1,19 @@
|
||||
# 0.6.22 (May 01, 2020)
|
||||
|
||||
### Added
|
||||
- Add support for illumos target (#1294)
|
||||
|
||||
# 0.6.21 (November 27, 2019)
|
||||
|
||||
### Fixed
|
||||
- remove `=` dependency on `cfg-if`.
|
||||
|
||||
# 0.6.20 (November 21, 2019)
|
||||
|
||||
### Fixed
|
||||
- Use default IOCP concurrency value (#1161).
|
||||
- setting FD_CLOEXEC in pipe (#1095).
|
||||
|
||||
# 0.6.19 (May 28, 2018)
|
||||
|
||||
### Fixed
|
||||
|
||||
21
Cargo.toml
21
Cargo.toml
@ -6,20 +6,22 @@ name = "mio"
|
||||
# - Update CHANGELOG.md.
|
||||
# - Update doc URL.
|
||||
# - Create git tag
|
||||
version = "0.6.19"
|
||||
version = "0.6.22"
|
||||
license = "MIT"
|
||||
authors = ["Carl Lerche <me@carllerche.com>"]
|
||||
description = "Lightweight non-blocking IO"
|
||||
documentation = "https://docs.rs/mio/0.6.19/mio/"
|
||||
homepage = "https://github.com/carllerche/mio"
|
||||
repository = "https://github.com/carllerche/mio"
|
||||
documentation = "https://docs.rs/mio/0.6.22/mio/"
|
||||
homepage = "https://github.com/tokio-rs/mio"
|
||||
repository = "https://github.com/tokio-rs/mio"
|
||||
readme = "README.md"
|
||||
keywords = ["io", "async", "non-blocking"]
|
||||
categories = ["asynchronous"]
|
||||
exclude = [
|
||||
".gitignore",
|
||||
".travis.yml",
|
||||
"deploy.sh",
|
||||
include = [
|
||||
"Cargo.toml",
|
||||
"LICENSE",
|
||||
"README.md",
|
||||
"CHANGELOG.md",
|
||||
"src/**/*.rs"
|
||||
]
|
||||
|
||||
[features]
|
||||
@ -31,13 +33,14 @@ log = "0.4"
|
||||
slab = "0.4.0"
|
||||
net2 = "0.2.29"
|
||||
iovec = "0.1.1"
|
||||
cfg-if = "0.1.9"
|
||||
|
||||
[target.'cfg(target_os = "fuchsia")'.dependencies]
|
||||
fuchsia-zircon = "0.3.2"
|
||||
fuchsia-zircon-sys = "0.3.2"
|
||||
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
libc = "0.2.42"
|
||||
libc = "0.2.54"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
winapi = "0.2.6"
|
||||
|
||||
@ -20,7 +20,7 @@ jobs:
|
||||
name: nightly
|
||||
displayName: Nightly
|
||||
# Pin nightly to avoid being impacted by breakage
|
||||
rust_version: nightly-2019-04-22
|
||||
rust_version: nightly-2019-11-17
|
||||
benches: true
|
||||
|
||||
# This represents the minimum Rust version supported by
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
#![feature(test)]
|
||||
#![allow(deprecated)]
|
||||
|
||||
extern crate mio;
|
||||
extern crate test;
|
||||
|
||||
@ -7,7 +7,7 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
iOS:
|
||||
vmImage: macOS-10.13
|
||||
vmImage: macOS-10.14
|
||||
target: x86_64-apple-ios
|
||||
|
||||
Android:
|
||||
|
||||
@ -2,7 +2,10 @@ steps:
|
||||
# Linux and macOS.
|
||||
- script: |
|
||||
set -e
|
||||
curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain $RUSTUP_TOOLCHAIN
|
||||
curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain none
|
||||
export PATH=$PATH:$HOME/.cargo/bin
|
||||
rustup toolchain install $RUSTUP_TOOLCHAIN
|
||||
rustup default $RUSTUP_TOOLCHAIN
|
||||
echo "##vso[task.setvariable variable=PATH;]$PATH:$HOME/.cargo/bin"
|
||||
env:
|
||||
RUSTUP_TOOLCHAIN: ${{parameters.rust_version}}
|
||||
@ -12,8 +15,10 @@ steps:
|
||||
# Windows.
|
||||
- script: |
|
||||
curl -sSf -o rustup-init.exe https://win.rustup.rs
|
||||
rustup-init.exe -y --default-toolchain %RUSTUP_TOOLCHAIN%
|
||||
rustup-init.exe -y --default-toolchain none
|
||||
set PATH=%PATH%;%USERPROFILE%\.cargo\bin
|
||||
rustup toolchain install %RUSTUP_TOOLCHAIN%
|
||||
rustup default %RUSTUP_TOOLCHAIN%
|
||||
echo "##vso[task.setvariable variable=PATH;]%PATH%;%USERPROFILE%\.cargo\bin"
|
||||
env:
|
||||
RUSTUP_TOOLCHAIN: ${{parameters.rust_version}}
|
||||
|
||||
@ -12,7 +12,7 @@ jobs:
|
||||
|
||||
${{ if parameters.cross }}:
|
||||
MacOS:
|
||||
vmImage: macOS-10.13
|
||||
vmImage: macOS-10.14
|
||||
Windows:
|
||||
vmImage: vs2017-win2016
|
||||
pool:
|
||||
@ -23,7 +23,10 @@ jobs:
|
||||
parameters:
|
||||
rust_version: ${{ parameters.rust_version }}
|
||||
|
||||
- script: cargo ${{ parameters.cmd }}
|
||||
- script: |
|
||||
cargo update
|
||||
cargo update -p cfg-if --precise 0.1.9
|
||||
cargo ${{ parameters.cmd }}
|
||||
displayName: cargo ${{ parameters.cmd }}
|
||||
env:
|
||||
CI: 'True'
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#![doc(html_root_url = "https://docs.rs/mio/0.6.19")]
|
||||
#![doc(html_root_url = "https://docs.rs/mio/0.6.22")]
|
||||
// Mio targets old versions of the Rust compiler. In order to do this, uses
|
||||
// deprecated APIs.
|
||||
#![allow(deprecated)]
|
||||
#![allow(bare_trait_objects, deprecated, unknown_lints)]
|
||||
#![deny(missing_docs, missing_debug_implementations)]
|
||||
#![cfg_attr(test, deny(warnings))]
|
||||
|
||||
|
||||
@ -30,21 +30,9 @@ pub struct Selector {
|
||||
impl Selector {
|
||||
pub fn new() -> io::Result<Selector> {
|
||||
let epfd = unsafe {
|
||||
// Emulate `epoll_create` by using `epoll_create1` if it's available
|
||||
// and otherwise falling back to `epoll_create` followed by a call to
|
||||
// set the CLOEXEC flag.
|
||||
dlsym!(fn epoll_create1(c_int) -> c_int);
|
||||
|
||||
match epoll_create1.get() {
|
||||
Some(epoll_create1_fn) => {
|
||||
cvt(epoll_create1_fn(libc::EPOLL_CLOEXEC))?
|
||||
}
|
||||
None => {
|
||||
let fd = cvt(libc::epoll_create(1024))?;
|
||||
drop(set_cloexec(fd));
|
||||
fd
|
||||
}
|
||||
}
|
||||
let fd = cvt(libc::epoll_create(1024))?;
|
||||
drop(set_cloexec(fd));
|
||||
fd
|
||||
};
|
||||
|
||||
// offset by 1 to avoid choosing 0 as the id of a selector
|
||||
|
||||
@ -3,10 +3,20 @@ use libc::{self, c_int};
|
||||
#[macro_use]
|
||||
pub mod dlsym;
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android", target_os = "solaris"))]
|
||||
#[cfg(any(
|
||||
target_os = "android",
|
||||
target_os = "illumos",
|
||||
target_os = "linux",
|
||||
target_os = "solaris"
|
||||
))]
|
||||
mod epoll;
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android", target_os = "solaris"))]
|
||||
#[cfg(any(
|
||||
target_os = "android",
|
||||
target_os = "illumos",
|
||||
target_os = "linux",
|
||||
target_os = "solaris"
|
||||
))]
|
||||
pub use self::epoll::{Events, Selector};
|
||||
|
||||
#[cfg(any(target_os = "bitrig", target_os = "dragonfly",
|
||||
@ -50,23 +60,27 @@ pub fn pipe() -> ::io::Result<(Io, Io)> {
|
||||
dlsym!(fn pipe2(*mut c_int, c_int) -> c_int);
|
||||
|
||||
let mut pipes = [0; 2];
|
||||
let flags = libc::O_NONBLOCK | libc::O_CLOEXEC;
|
||||
unsafe {
|
||||
match pipe2.get() {
|
||||
Some(pipe2_fn) => {
|
||||
let flags = libc::O_NONBLOCK | libc::O_CLOEXEC;
|
||||
cvt(pipe2_fn(pipes.as_mut_ptr(), flags))?;
|
||||
Ok((Io::from_raw_fd(pipes[0]), Io::from_raw_fd(pipes[1])))
|
||||
}
|
||||
None => {
|
||||
cvt(libc::pipe(pipes.as_mut_ptr()))?;
|
||||
libc::fcntl(pipes[0], libc::F_SETFL, flags);
|
||||
libc::fcntl(pipes[1], libc::F_SETFL, flags);
|
||||
// Ensure the pipe are closed if any of the system calls below
|
||||
// fail.
|
||||
let r = Io::from_raw_fd(pipes[0]);
|
||||
let w = Io::from_raw_fd(pipes[1]);
|
||||
cvt(libc::fcntl(pipes[0], libc::F_SETFD, libc::FD_CLOEXEC))?;
|
||||
cvt(libc::fcntl(pipes[1], libc::F_SETFD, libc::FD_CLOEXEC))?;
|
||||
cvt(libc::fcntl(pipes[0], libc::F_SETFL, libc::O_NONBLOCK))?;
|
||||
cvt(libc::fcntl(pipes[1], libc::F_SETFL, libc::O_NONBLOCK))?;
|
||||
Ok((r, w))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe {
|
||||
Ok((Io::from_raw_fd(pipes[0]), Io::from_raw_fd(pipes[1])))
|
||||
}
|
||||
}
|
||||
|
||||
trait IsMinusOne {
|
||||
|
||||
@ -109,10 +109,20 @@ const LIO: usize = 0b10_0000;
|
||||
#[cfg(not(any(target_os = "freebsd")))]
|
||||
const LIO: usize = 0b00_0000;
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android", target_os = "solaris"))]
|
||||
#[cfg(any(
|
||||
target_os = "android",
|
||||
target_os = "illumos",
|
||||
target_os = "linux",
|
||||
target_os = "solaris"
|
||||
))]
|
||||
const PRI: usize = 0b100_0000;
|
||||
|
||||
#[cfg(not(any(target_os = "linux", target_os = "android", target_os = "solaris")))]
|
||||
#[cfg(not(any(
|
||||
target_os = "android",
|
||||
target_os = "illumos",
|
||||
target_os = "linux",
|
||||
target_os = "solaris"
|
||||
)))]
|
||||
const PRI: usize = 0;
|
||||
|
||||
// Export to support `Ready::all`
|
||||
@ -129,7 +139,12 @@ fn test_ready_all() {
|
||||
);
|
||||
|
||||
// Issue #896.
|
||||
#[cfg(any(target_os = "linux", target_os = "android", target_os = "solaris"))]
|
||||
#[cfg(any(
|
||||
target_os = "android",
|
||||
target_os = "illumos",
|
||||
target_os = "linux",
|
||||
target_os = "solaris"
|
||||
))]
|
||||
assert!(!Ready::from(UnixReady::priority()).is_writable());
|
||||
}
|
||||
|
||||
@ -258,8 +273,12 @@ impl UnixReady {
|
||||
///
|
||||
/// [`Poll`]: struct.Poll.html
|
||||
#[inline]
|
||||
#[cfg(any(target_os = "linux",
|
||||
target_os = "android", target_os = "solaris"))]
|
||||
#[cfg(any(
|
||||
target_os = "android",
|
||||
target_os = "illumos",
|
||||
target_os = "linux",
|
||||
target_os = "solaris"
|
||||
))]
|
||||
pub fn priority() -> UnixReady {
|
||||
UnixReady(ready_from_usize(PRI))
|
||||
}
|
||||
@ -385,8 +404,12 @@ impl UnixReady {
|
||||
///
|
||||
/// [`Poll`]: struct.Poll.html
|
||||
#[inline]
|
||||
#[cfg(any(target_os = "linux",
|
||||
target_os = "android", target_os = "solaris"))]
|
||||
#[cfg(any(
|
||||
target_os = "android",
|
||||
target_os = "illumos",
|
||||
target_os = "linux",
|
||||
target_os = "solaris"
|
||||
))]
|
||||
pub fn is_priority(&self) -> bool {
|
||||
self.contains(ready_from_usize(PRI))
|
||||
}
|
||||
@ -476,8 +499,12 @@ impl fmt::Debug for UnixReady {
|
||||
(UnixReady::hup(), "Hup"),
|
||||
#[allow(deprecated)]
|
||||
(UnixReady::aio(), "Aio"),
|
||||
#[cfg(any(target_os = "linux",
|
||||
target_os = "android", target_os = "solaris"))]
|
||||
#[cfg(any(
|
||||
target_os = "android",
|
||||
target_os = "illumos",
|
||||
target_os = "linux",
|
||||
target_os = "solaris"
|
||||
))]
|
||||
(UnixReady::priority(), "Priority"),
|
||||
];
|
||||
|
||||
|
||||
@ -55,7 +55,7 @@ impl Selector {
|
||||
// offset by 1 to avoid choosing 0 as the id of a selector
|
||||
let id = NEXT_ID.fetch_add(1, Ordering::Relaxed) + 1;
|
||||
|
||||
CompletionPort::new(1).map(|cp| {
|
||||
CompletionPort::new(0).map(|cp| {
|
||||
Selector {
|
||||
inner: Arc::new(SelectorInner {
|
||||
id: id,
|
||||
|
||||
@ -181,7 +181,6 @@ mod ports {
|
||||
|
||||
pub fn sleep_ms(ms: u64) {
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
thread::sleep(Duration::from_millis(ms));
|
||||
}
|
||||
|
||||
|
||||
@ -1,73 +1,262 @@
|
||||
use std::net::Shutdown;
|
||||
use std::time::Duration;
|
||||
use std::collections::HashMap;
|
||||
use std::net::{self, Shutdown};
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
use mio::{Token, Ready, PollOpt, Poll, Events};
|
||||
use mio::event::{Evented, Event};
|
||||
use mio::net::TcpStream;
|
||||
|
||||
macro_rules! wait {
|
||||
($poll:ident, $ready:ident) => {{
|
||||
use std::time::Instant;
|
||||
struct TestPoll {
|
||||
poll: Poll,
|
||||
events: Events,
|
||||
buf: HashMap<Token, Ready>,
|
||||
}
|
||||
|
||||
impl TestPoll {
|
||||
fn new() -> TestPoll {
|
||||
TestPoll {
|
||||
poll: Poll::new().unwrap(),
|
||||
events: Events::with_capacity(1024),
|
||||
buf: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn register<E: ?Sized>(&self, handle: &E, token: Token, interest: Ready, opts: PollOpt)
|
||||
where E: Evented
|
||||
{
|
||||
self.poll.register(handle, token, interest, opts).unwrap();
|
||||
}
|
||||
|
||||
fn wait_for(&mut self, token: Token, ready: Ready) -> Result<(), &'static str> {
|
||||
let now = Instant::now();
|
||||
let mut events = Events::with_capacity(16);
|
||||
let mut found = false;
|
||||
|
||||
while !found {
|
||||
if now.elapsed() > Duration::from_secs(5) {
|
||||
panic!("not ready");
|
||||
loop {
|
||||
if now.elapsed() > Duration::from_secs(1) {
|
||||
return Err("not ready");
|
||||
}
|
||||
|
||||
$poll.poll(&mut events, Some(Duration::from_secs(1))).unwrap();
|
||||
|
||||
for event in &events {
|
||||
#[cfg(unix)]
|
||||
{
|
||||
use mio::unix::UnixReady;
|
||||
assert!(!UnixReady::from(event.readiness()).is_hup());
|
||||
}
|
||||
|
||||
if event.token() == Token(0) && event.readiness().$ready() {
|
||||
found = true;
|
||||
if let Some(curr) = self.buf.get(&token) {
|
||||
if curr.contains(ready) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
self.poll.poll(&mut self.events, Some(Duration::from_millis(250))).unwrap();
|
||||
|
||||
for event in &self.events {
|
||||
let curr = self.buf.entry(event.token())
|
||||
.or_insert(Ready::empty());
|
||||
|
||||
*curr |= event.readiness();
|
||||
}
|
||||
}
|
||||
|
||||
*self.buf.get_mut(&token).unwrap() -= ready;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn check_idle(&mut self) -> Result<(), Event> {
|
||||
self.poll.poll(&mut self.events, Some(Duration::from_millis(100))).unwrap();
|
||||
|
||||
if let Some(e) = self.events.iter().next() {
|
||||
Err(e)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! assert_ready {
|
||||
($poll:expr, $token:expr, $ready:expr) => {{
|
||||
match $poll.wait_for($token, $ready) {
|
||||
Ok(_) => {}
|
||||
Err(_) => panic!("not ready; token = {:?}; interest = {:?}", $token, $ready),
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
||||
macro_rules! assert_not_ready {
|
||||
($poll:expr, $token:expr, $ready:expr) => {{
|
||||
match $poll.wait_for($token, $ready) {
|
||||
Ok(_) => panic!("is ready; token = {:?}; interest = {:?}", $token, $ready),
|
||||
Err(_) => {}
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
||||
macro_rules! assert_hup_ready {
|
||||
($poll:expr) => {
|
||||
#[cfg(unix)]
|
||||
{
|
||||
use mio::unix::UnixReady;
|
||||
assert_ready!($poll, Token(0), Ready::from(UnixReady::hup()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! assert_not_hup_ready {
|
||||
($poll:expr) => {
|
||||
#[cfg(unix)]
|
||||
{
|
||||
use mio::unix::UnixReady;
|
||||
assert_not_ready!($poll, Token(0), Ready::from(UnixReady::hup()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! assert_idle {
|
||||
($poll:expr) => {
|
||||
match $poll.check_idle() {
|
||||
Ok(()) => {}
|
||||
Err(e) => panic!("not idle; event = {:?}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: replace w/ assertive
|
||||
// https://github.com/carllerche/assertive
|
||||
macro_rules! assert_ok {
|
||||
($e:expr) => {
|
||||
assert_ok!($e,)
|
||||
};
|
||||
($e:expr,) => {{
|
||||
use std::result::Result::*;
|
||||
match $e {
|
||||
Ok(v) => v,
|
||||
Err(e) => panic!("assertion failed: error = {:?}", e),
|
||||
}
|
||||
}};
|
||||
($e:expr, $($arg:tt)+) => {{
|
||||
use std::result::Result::*;
|
||||
match $e {
|
||||
Ok(v) => v,
|
||||
Err(e) => panic!("assertion failed: error = {:?}: {}", e, format_args!($($arg)+)),
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_write_shutdown() {
|
||||
let poll = Poll::new().unwrap();
|
||||
use std::io::prelude::*;
|
||||
|
||||
let listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap();
|
||||
let addr = listener.local_addr().unwrap();
|
||||
let mut poll = TestPoll::new();
|
||||
let mut buf = [0; 1024];
|
||||
|
||||
let mut ready = Ready::readable() | Ready::writable();
|
||||
let listener = assert_ok!(net::TcpListener::bind("127.0.0.1:0"));
|
||||
let addr = assert_ok!(listener.local_addr());
|
||||
|
||||
#[cfg(unix)]
|
||||
{
|
||||
ready |= mio::unix::UnixReady::hup();
|
||||
}
|
||||
|
||||
let client = TcpStream::connect(&addr).unwrap();
|
||||
let mut client = assert_ok!(TcpStream::connect(&addr));
|
||||
poll.register(&client,
|
||||
Token(0),
|
||||
ready,
|
||||
PollOpt::edge()).unwrap();
|
||||
Ready::readable() | Ready::writable(),
|
||||
PollOpt::edge());
|
||||
|
||||
let (socket, _) = listener.accept().unwrap();
|
||||
let (socket, _) = assert_ok!(listener.accept());
|
||||
|
||||
wait!(poll, is_writable);
|
||||
|
||||
let mut events = Events::with_capacity(16);
|
||||
assert_ready!(poll, Token(0), Ready::writable());
|
||||
|
||||
// Polling should not have any events
|
||||
poll.poll(&mut events, Some(Duration::from_millis(100))).unwrap();
|
||||
assert!(events.iter().next().is_none());
|
||||
assert_idle!(poll);
|
||||
|
||||
println!("SHUTTING DOWN");
|
||||
// Now, shutdown the write half of the socket.
|
||||
socket.shutdown(Shutdown::Write).unwrap();
|
||||
assert_ok!(socket.shutdown(Shutdown::Write));
|
||||
|
||||
wait!(poll, is_readable);
|
||||
assert_ready!(poll, Token(0), Ready::readable());
|
||||
|
||||
assert_not_hup_ready!(poll);
|
||||
|
||||
let n = assert_ok!(client.read(&mut buf));
|
||||
assert_eq!(n, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_graceful_shutdown() {
|
||||
use std::io::prelude::*;
|
||||
|
||||
let mut poll = TestPoll::new();
|
||||
let mut buf = [0; 1024];
|
||||
|
||||
let listener = assert_ok!(net::TcpListener::bind("127.0.0.1:0"));
|
||||
let addr = assert_ok!(listener.local_addr());
|
||||
|
||||
let mut client = assert_ok!(TcpStream::connect(&addr));
|
||||
poll.register(&client,
|
||||
Token(0),
|
||||
Ready::readable() | Ready::writable(),
|
||||
PollOpt::edge());
|
||||
|
||||
let (mut socket, _) = assert_ok!(listener.accept());
|
||||
|
||||
assert_ready!(poll, Token(0), Ready::writable());
|
||||
|
||||
// Polling should not have any events
|
||||
assert_idle!(poll);
|
||||
|
||||
// Now, shutdown the write half of the socket.
|
||||
assert_ok!(client.shutdown(Shutdown::Write));
|
||||
|
||||
let n = assert_ok!(socket.read(&mut buf));
|
||||
assert_eq!(0, n);
|
||||
drop(socket);
|
||||
|
||||
assert_ready!(poll, Token(0), Ready::readable());
|
||||
#[cfg(not(any(
|
||||
target_os = "bitrig",
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd"
|
||||
)))]
|
||||
assert_hup_ready!(poll);
|
||||
|
||||
let mut buf = [0; 1024];
|
||||
let n = assert_ok!(client.read(&mut buf));
|
||||
assert_eq!(n, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_abrupt_shutdown() {
|
||||
use net2::TcpStreamExt;
|
||||
use std::io::Read;
|
||||
|
||||
let mut poll = TestPoll::new();
|
||||
let mut buf = [0; 1024];
|
||||
|
||||
let listener = assert_ok!(net::TcpListener::bind("127.0.0.1:0"));
|
||||
let addr = assert_ok!(listener.local_addr());
|
||||
|
||||
let mut client = assert_ok!(TcpStream::connect(&addr));
|
||||
poll.register(&client,
|
||||
Token(0),
|
||||
Ready::readable() | Ready::writable(),
|
||||
PollOpt::edge());
|
||||
|
||||
let (socket, _) = assert_ok!(listener.accept());
|
||||
assert_ok!(socket.set_linger(Some(Duration::from_millis(0))));
|
||||
// assert_ok!(socket.set_linger(None));
|
||||
|
||||
// Wait to be connected
|
||||
assert_ready!(poll, Token(0), Ready::writable());
|
||||
|
||||
drop(socket);
|
||||
|
||||
#[cfg(not(any(
|
||||
target_os = "bitrig",
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd"
|
||||
)))]
|
||||
assert_hup_ready!(poll);
|
||||
assert_ready!(poll, Token(0), Ready::writable());
|
||||
assert_ready!(poll, Token(0), Ready::readable());
|
||||
|
||||
let res = client.read(&mut buf);
|
||||
assert!(res.is_err(), "not err = {:?}", res);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user