Comments (6)
Well thanks a lot, you definitely helped me! I will close this, as it has nothing to do with mio :)
from mio.
In general it's ok to try an I/O operations even if you don't get an event for it. However you have to handle the WouldBlock
error returned at that point, but this can be returned even after you do get an event, so really it doesn't change the error handling.
As for the not getting a writable event, can you share some code that demonstrates that? Because we have tests for it:
Lines 123 to 145 in 9f21ce1
from mio.
Thank you!
That makes sense.
As for the TX events:
The following is what my usecase boils down to:
# Cargo.toml
[package]
name = "udp_test"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
libc = "0.2.148"
mio = { version = "0.8", features = ["os-ext", "os-poll", "net"] }
use std::{io::{self, ErrorKind, Write}, net::SocketAddr, thread, os::fd::AsRawFd, time::Duration};
use mio::{Token, Poll, unix::pipe::Receiver, Events, Interest, net::UdpSocket};
const UDP: Token = Token(0);
const PRODUCER: Token = Token(1);
fn main() -> io::Result<()> {
// register event sources
let port = 4242u16;
let listen_addr = SocketAddr::new("0.0.0.0".parse().unwrap(), port);
let mut socket = UdpSocket::bind(listen_addr)?;
let (pipe_tx, mut pipe_rx) = mio::unix::pipe::new()?;
pipe_rx.set_nonblocking(true)?;
let mut poll = Poll::new()?;
poll.registry().register(&mut socket, UDP, Interest::READABLE | Interest::WRITABLE)?;
poll.registry().register(&mut pipe_rx, PRODUCER, Interest::READABLE)?;
// producer thread writing stuff onto the pipe in intervals
thread::spawn(move || {
loop {
let buf = b"test";
if let Err(e) = pipe_tx.try_io(|| {
let buf_ptr = &buf as *const _ as *const _;
let res = unsafe { libc::write(pipe_tx.as_raw_fd(), buf_ptr, buf.len()) };
if res != -1 {
Ok(res as usize)
} else {
Err(io::Error::last_os_error())
}
}) {
eprintln!("{e}");
}
thread::sleep(Duration::from_millis(10));
}
});
let mut events = Events::with_capacity(10);
loop {
poll.poll(&mut events, None)?;
for event in &events {
match event.token() {
UDP => {
if event.is_readable() {
handle_udp_rx(&socket);
println!("udp RX {:?}", event);
}
if event.is_writable() {
println!("udp TX {:?}", event);
}
}
PRODUCER => {
handle_producer(&pipe_rx, &socket);
}
_ => panic!()
}
}
events.clear();
}
}
fn handle_udp_rx(socket: &UdpSocket) {
loop {
let mut buf = vec![0u8; 4];
let (count, addr) = match socket.recv_from(&mut buf) {
Ok((count, addr)) => (count, addr),
Err(e) if e.kind() == ErrorKind::WouldBlock => return,
Err(e) => {
eprintln!("{}", e);
continue
}
};
println!("{addr} {:?} ({count})", buf);
}
}
fn handle_producer(pipe_rx: &Receiver, socket: &UdpSocket) {
let mut buf = [0u8; 4];
if let Err(e) = pipe_rx.try_io(|| {
let buf_ptr = &mut buf as *mut _ as *mut _;
let res = unsafe { libc::read(pipe_rx.as_raw_fd(), buf_ptr, buf.len()) };
if res != -1 {
Ok(res as usize)
} else {
Err(io::Error::last_os_error())
}
}) {
println!("{e}");
}
if let Err(e) = socket.send_to(&buf, "192.168.178.189:4242".parse::<SocketAddr>().unwrap()) {
// eprintln!("{e}");
eprint!("e");
} else {
eprint!(".");
}
std::io::stderr().flush().unwrap();
if let Err(e) = socket.send_to(&buf, "192.168.178.172:4242".parse::<SocketAddr>().unwrap()) {
// eprintln!("{e}");
eprint!("e");
} else {
eprint!(".");
}
std::io::stderr().flush().unwrap();
if let Err(e) = socket.send_to(&buf, "192.168.178.125:4242".parse::<SocketAddr>().unwrap()) {
// eprintln!("{e}");
eprint!("e");
} else {
eprint!(".");
}
std::io::stderr().flush().unwrap();
}
It results in an output that looks like this:
..............................................................................................................................................................................................................................................eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeudp TX Event { token: Token(0), readable: false, writable: true, error: false, read_closed: false, write_closed: false, priority: false, aio: false, lio: false }
..............................................................................................................................................................................................................................................eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeudp TX Event { token: Token(0), readable: false, writable: true, error: false, read_closed: false, write_closed: false, priority: false, aio: false, lio: false }
..............................................................................................................................................................................................................................................eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeudp TX Event { token: Token(0), readable: false, writable: true, error: false, read_closed: false, write_closed: false, priority: false, aio: false, lio: false }
..............................................................................................................................................................................................................................................eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
I kind of expected to receive a tx event everytime I could write to the socket (which should be after each .
)
The printed e
s correspond to WouldBlock errors (errno 11).
So I assume that has to do with the level triggered event type?
Now my real problem is the fact that sometimes it takes ~3 seconds until a new sendto() is possible.
Do you happen to know why that might be?
I read somewhere it might have to do with arp requests blocking the send...
So this likely may not be related to mio at all.
from mio.
Thank you!
That makes sense.
As for the TX events: The following is what my usecase boils down to:
# Cargo.toml [package] name = "udp_test" version = "0.1.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] libc = "0.2.148" mio = { version = "0.8", features = ["os-ext", "os-poll", "net"] }use std::{io::{self, ErrorKind, Write}, net::SocketAddr, thread, os::fd::AsRawFd, time::Duration}; use mio::{Token, Poll, unix::pipe::Receiver, Events, Interest, net::UdpSocket}; const UDP: Token = Token(0); const PRODUCER: Token = Token(1); fn main() -> io::Result<()> { // register event sources let port = 4242u16; let listen_addr = SocketAddr::new("0.0.0.0".parse().unwrap(), port); let mut socket = UdpSocket::bind(listen_addr)?; let (pipe_tx, mut pipe_rx) = mio::unix::pipe::new()?; pipe_rx.set_nonblocking(true)?;
Mio's unix pipes are already non-blocking, so this is not needed.
let mut poll = Poll::new()?; poll.registry().register(&mut socket, UDP, Interest::READABLE | Interest::WRITABLE)?; poll.registry().register(&mut pipe_rx, PRODUCER, Interest::READABLE)?; // producer thread writing stuff onto the pipe in intervals thread::spawn(move || { loop { let buf = b"test"; if let Err(e) = pipe_tx.try_io(|| { let buf_ptr = &buf as *const _ as *const _; let res = unsafe { libc::write(pipe_tx.as_raw_fd(), buf_ptr, buf.len()) }; if res != -1 { Ok(res as usize) } else { Err(io::Error::last_os_error()) }
Why not pipe_tx.write
(from the std::io::Write
trait)?
}) { eprintln!("{e}"); } thread::sleep(Duration::from_millis(10)); } }); let mut events = Events::with_capacity(10); loop { poll.poll(&mut events, None)?; for event in &events { match event.token() { UDP => { if event.is_readable() { handle_udp_rx(&socket); println!("udp RX {:?}", event); } if event.is_writable() { println!("udp TX {:?}", event); } } PRODUCER => { handle_producer(&pipe_rx, &socket); } _ => panic!() } } events.clear(); }
}
fn handle_udp_rx(socket: &UdpSocket) {
loop {
let mut buf = vec![0u8; 4];
let (count, addr) = match socket.recv_from(&mut buf) {
Ok((count, addr)) => (count, addr),
Err(e) if e.kind() == ErrorKind::WouldBlock => return,
Err(e) => {
eprintln!("{}", e);
continue
}
};
println!("{addr} {:?} ({count})", buf);
This should be buf[n..]
as the bytes after n
aren't written.
}
}
fn handle_producer(pipe_rx: &Receiver, socket: &UdpSocket) {
let mut buf = [0u8; 4];
if let Err(e) = pipe_rx.try_io(|| {
let buf_ptr = &mut buf as *mut _ as *mut _;
let res = unsafe { libc::read(pipe_rx.as_raw_fd(), buf_ptr, buf.len()) };
if res != -1 {
Ok(res as usize)
} else {
Err(io::Error::last_os_error())
}
Can do pipe_rx.read(&mut buf)
here (from the std::io::Read
trait).
}) { println!("{e}"); } if let Err(e) = socket.send_to(&buf, "192.168.178.189:4242".parse::<SocketAddr>().unwrap()) {
Are you sure this IP works? Why not use 127.0.0.1
? That is localhost and should always work.
// eprintln!("{e}"); eprint!("e"); } else { eprint!("."); } std::io::stderr().flush().unwrap(); if let Err(e) = socket.send_to(&buf, "192.168.178.172:4242".parse::<SocketAddr>().unwrap()) { // eprintln!("{e}"); eprint!("e"); } else { eprint!("."); } std::io::stderr().flush().unwrap(); if let Err(e) = socket.send_to(&buf, "192.168.178.125:4242".parse::<SocketAddr>().unwrap()) { // eprintln!("{e}"); eprint!("e"); } else { eprint!("."); } std::io::stderr().flush().unwrap();
}
It results in an output that looks like this:
..............................................................................................................................................................................................................................................eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeudp TX Event { token: Token(0), readable: false, writable: true, error: false, read_closed: false, write_closed: false, priority: false, aio: false, lio: false }
..............................................................................................................................................................................................................................................eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeudp TX Event { token: Token(0), readable: false, writable: true, error: false, read_closed: false, write_closed: false, priority: false, aio: false, lio: false }
..............................................................................................................................................................................................................................................eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeudp TX Event { token: Token(0), readable: false, writable: true, error: false, read_closed: false, write_closed: false, priority: false, aio: false, lio: false }
..............................................................................................................................................................................................................................................eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeI kind of expected to receive a tx event everytime I could write to the socket (which should be after each `.`) The printed `e`s correspond to WouldBlock errors (errno 11). So I assume that has to do with the level triggered event type? Now my real problem is the fact that sometimes it takes ~3 seconds until a new sendto() is possible. Do you happen to know why that might be? I read somewhere it might have to do with arp requests blocking the send...
That can be because of a range of reasons. Running anti-virus/malware software by any chance?
So this likely may not be related to mio at all.
It would recommend enabling debug logging for Mio, it will show all events that it processes.
from mio.
Thank you for the suggestion, I just forgot about the Read and Write traits ... (kind of new to rust).
I'm on Linux and not using any AV software and also tried this with the firewall disabled.
The ips correspond to different interfaces on my laptop, with only one of them reachable.
I wanted to ping them and see which one responds.
What's strange is the fact, that all of this works, as long as I dont send to more than one of the ips.
(I can send packages to either of the ips indefinitely without getting WouldBlock)
however if I send to multiple interfaces these 3 second delays occur.
from mio.
What's strange is the fact, that all of this works, as long as I dont send to more than one of the ips.
(I can send packages to either of the ips indefinitely without getting WouldBlock)
however if I send to multiple interfaces these 3 second delays occur.
I don't have a good explanation for this either.
from mio.
Related Issues (20)
- poll: Optimize locks and allocations in the critical path
- Poll(2) implementation follow-ups
- Official ESP-IDF framework support HOT 3
- Make `CompletionPort` public? HOT 7
- No data coming from Poll HOT 8
- Difference behaves between Linux and Windows HOT 2
- could not compile mio due to 44 previous errors HOT 3
- WakerRegistrar mentioned in comment is not present HOT 2
- Decide MSRV for v1 HOT 2
- Use rustix instead of libc HOT 2
- Document MSRV policy HOT 1
- Update socket types API to match std lib HOT 5
- unresolved imports in target xtensa-esp32-espidf HOT 7
- `syscall!` macros hide unsafe code HOT 2
- why is it possible to create a mio TcpStream from std TcpStream but going the other way around is unsafe? HOT 13
- peek blocks after read on windows HOT 7
- Poll changing interest of server socket on Windows HOT 1
- Cannot continue listen! HOT 2
- Walker failure on Linux HOT 6
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from mio.