I am writing a process to move data back and forth between instances of itself.
I am receiving the error:
thread 'main' panicked at 'called
Result::unwrap()
on anErr
value: Os { code: 11, kind: WouldBlock, message: "Resource temporarily unavailable" }', server/src/main.rs:44:37
My current implementation:
#![feature(duration_constants)]
use std::os::unix::net::UnixDatagram;
use std::time::Duration;
const OLD_PROCESS: &str = "./old";
const NEW_PROCESS: &str = "./new";
fn startup() {
// We send the shutdown notification (the data here doesnt matter) then receive the data.
let socket = UnixDatagram::bind(NEW_PROCESS).unwrap();
println!("sending shutdown signal");
socket.send_to(&[1], OLD_PROCESS).unwrap();
println!("sent shutdown signal");
println!("reciving data");
let mut data = [Default::default(); 4];
socket.recv(&mut data).unwrap();
println!("data: {:?}", data);
std::fs::remove_file(NEW_PROCESS).unwrap();
}
fn process() {
// Once we receive something (indicating a new process has started) we then transfer data.
let socket = UnixDatagram::bind(OLD_PROCESS).unwrap();
println!("awaiting shutdown signal");
// For reading the shutdown signal, we set the socket to non-blocking (like `Mutex::try_read`).
let mut notif_buf = [0; 1];
// It seems by setting nonblocking and the read timeout causes the error:
// ```
// thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Os { code: 11, kind: WouldBlock, message: "Resource temporarily unavailable" }', server/src/main.rs:44:37
// ```
socket.set_nonblocking(true).unwrap();
socket
.set_read_timeout(Some(Duration::MICROSECOND))
.unwrap();
println!("socket.read_timeout(): {:?}", socket.read_timeout());
// Our work loop
while notif_buf[0] == 0 {
// Some other work
{
print!(".");
std::thread::sleep(Duration::MILLISECOND);
}
// Check if recieved shutdown signal
socket.recv(&mut notif_buf).unwrap();
}
println!();
println!("recived shutdown signal");
socket.set_nonblocking(false).unwrap();
println!("sending data");
socket.send_to(&[1, 2, 3, 4], NEW_PROCESS).unwrap();
println!("sent data");
std::fs::remove_file(OLD_PROCESS).unwrap();
}
fn main() {
println!("Hello, world!");
// The following processes use it
if std::path::Path::new(OLD_PROCESS).exists() {
println!("non-first");
startup();
process();
}
// The first process creates the socket
else {
println!("first");
process();
}
}
Notably with this you will need to delete the old
file descriptor at the end of each test manually for now
In the simplest sense I want a loop with UnixDatagram like (with try_read
like Mutex::try_read
):
loop {
// Some work ...
match socket.try_read() {
Some(_) => break,
None => continue
}
}
When using:
socket.set_nonblocking(true).unwrap();
socket.set_read_timeout(Some(Duration::MICROSECOND)).unwrap();
it seems when the timeout occurs recv
returns Err
thus by changing the code:
// Check if recieved shutdown signal
socket.recv(&mut notif_buf).unwrap();
to
match socket.recv(&mut notif_buf) {
Ok(_) => break,
Err(_) if err.kind() == ErrorKind::WouldBlock => continue,
_ => unreachable!()
}
this fixes the issue.