// `a` is not readable, but the reactor still thinks it is // (because we have not observed a not-ready error yet)
afd_a.readable().await.unwrap().retain_ready();
// Explicitly clear the ready state
guard.clear_ready();
let readable = afd_a.readable();
tokio::pin!(readable);
// Drop closure behavior is delegated to the inner object let (a, mut b) = socketpair(); let arc_fd = Arc::new(a); let afd_a = AsyncFd::new(ArcFd(arc_fd.clone())).unwrap();
std::mem::drop(afd_a);
#[tokio::test] asyncfn poll_fns() { let (a, b) = socketpair(); let afd_a = Arc::new(AsyncFd::new(a).unwrap()); let afd_b = Arc::new(AsyncFd::new(b).unwrap());
// Fill up the write side of A while afd_a.get_ref().write(&[0; 512]).is_ok() {}
// Make A readable. We expect that 'readable' and 'read_fut' will both complete quickly
afd_b.get_ref().write_all(b"0").unwrap();
let _ = tokio::join!(readable, read_fut);
// Our original waker should _not_ be awoken (poll_read_ready retains only the last context)
assert!(!waker.awoken());
// The writable side should not be awoken
tokio::select! {
_ = &mut write_fut => unreachable!(),
_ = tokio::time::sleep(Duration::from_millis(5)) => {}
}
// Make it writable now
drain(afd_b.get_ref());
// now we should be writable (ie - the waker for poll_write should still be registered after we wake the read side) let _ = write_fut.await;
}
#[test] fn driver_shutdown_wakes_currently_pending_polls() { let rt = rt();
let (a, _b) = socketpair(); let afd_a = { let _enter = rt.enter();
AsyncFd::new(a).unwrap()
};
while afd_a.get_ref().write(&[0; 512]).is_ok() {} // make not writable
let readable = assert_pending(poll_readable(&afd_a)); let writable = assert_pending(poll_writable(&afd_a));
std::mem::drop(rt);
// Attempting to poll readiness when the rt is dropped is an error
assert_err!(futures::executor::block_on(readable));
assert_err!(futures::executor::block_on(writable));
}
#[test] fn driver_shutdown_wakes_poll() { let rt = rt();
let (a, _b) = socketpair(); let afd_a = { let _enter = rt.enter();
AsyncFd::new(a).unwrap()
};
#[test] fn driver_shutdown_wakes_poll_race() { // TODO: make this a loom test for _ in0..100 { let rt = rt();
let (a, _b) = socketpair(); let afd_a = { let _enter = rt.enter();
AsyncFd::new(a).unwrap()
};
while afd_a.get_ref().write(&[0; 512]).is_ok() {} // make not writable
let _ = std::thread::spawn(move || std::mem::drop(rt));
// The poll variants will always return an error in this case
assert_err!(futures::executor::block_on(poll_readable(&afd_a)));
assert_err!(futures::executor::block_on(poll_writable(&afd_a)));
}
}
let buf = b"hello there";
fd.get_ref().send(buf).unwrap();
// the send timestamp should now be in the error queue let guard = fd.ready(Interest::ERROR).await.unwrap();
assert_eq!(guard.ready(), Ready::ERROR);
}
let res = unsafe {
libc::setsockopt(
udp_socket.as_raw_fd(),
libc::SOL_SOCKET,
libc::SO_TIMESTAMP,
&options as *const _ as *const libc::c_void,
std::mem::size_of_val(&options) as libc::socklen_t,
)
};
if res == -1 {
Err(std::io::Error::last_os_error())
} else {
Ok(res)
}
}
#[tokio::test] #[cfg(target_os = "linux")] asyncfn await_error_readiness_invalid_address() { use std::net::{Ipv4Addr, SocketAddr}; use tokio::io::{Interest, Ready};
let socket_addr = SocketAddr::from((Ipv4Addr::LOCALHOST, 0)); let socket = std::net::UdpSocket::bind(socket_addr).unwrap(); let socket_fd = socket.as_raw_fd();
// Enable IP_RECVERR option to receive error messages // https://man7.org/linux/man-pages/man7/ip.7.html has some extra information let recv_err: libc::c_int = 1; unsafe { let res = libc::setsockopt(
socket.as_raw_fd(),
libc::SOL_IP,
libc::IP_RECVERR,
&recv_err as *const _ as *const libc::c_void,
std::mem::size_of_val(&recv_err) as libc::socklen_t,
); if res == -1 {
panic!("{:?}", std::io::Error::last_os_error());
}
}
// Spawn a separate thread for sending messages
tokio::spawn(asyncmove { // Set the destination address. This address is invalid in this context. the OS will notice // that nobody is listening on port this port. Normally this is ignored (UDP is "fire and forget"), // but because IP_RECVERR is enabled, the error will actually be reported to the sending socket letmut dest_addr = unsafe { std::mem::MaybeUninit::<libc::sockaddr_in>::zeroed().assume_init() };
dest_addr.sin_family = libc::AF_INET as _; // based on https://en.wikipedia.org/wiki/Ephemeral_port, we should pick a port number // below 1024 to guarantee that other tests don't select this port by accident when they // use port 0 to select an ephemeral port.
dest_addr.sin_port = 512u16.to_be(); // Destination port
// Prepare the message data let message = "Hello, Socket!";
// Prepare the message structure for sendmsg letmut iov = libc::iovec {
iov_base: message.as_ptr() as *mut libc::c_void,
iov_len: message.len(),
};
// Prepare the destination address for the sendmsg call let dest_sockaddr: *const libc::sockaddr = &dest_addr as *const _ as *const libc::sockaddr; let dest_addrlen: libc::socklen_t = std::mem::size_of_val(&dest_addr) as libc::socklen_t;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.