Announce when ready to dup

This commit is contained in:
jD91mZM2
2018-06-02 11:56:51 +02:00
parent 974d37f8e2
commit eae2252c5f
2 changed files with 78 additions and 26 deletions
+50 -11
View File
@@ -17,6 +17,8 @@ fn main() -> io::Result<()> {
let server = File::create("chan:hello_world")?;
{
let mut client = File::open("chan:hello_world")?;
// First client not accepted yet
assert_eq!(File::open("chan:hello_world").unwrap_err().kind(), io::ErrorKind::ConnectionRefused);
let dup = syscall::dup(server.as_raw_fd(), b"listen").map_err(from_syscall_error)?;
let mut dup = unsafe { File::from_raw_fd(dup) };
@@ -65,7 +67,21 @@ fn main() -> io::Result<()> {
syscall::fcntl(client.as_raw_fd(), syscall::F_SETFL, syscall::O_NONBLOCK)
.map_err(from_syscall_error)?;
syscall::fcntl(server.as_raw_fd(), syscall::F_SETFL, syscall::O_NONBLOCK)
.map_err(from_syscall_error)?;
assert_eq!(client.read(&mut buf).unwrap_err().kind(), io::ErrorKind::WouldBlock);
println!("-> Read would block");
match syscall::dup(server.as_raw_fd(), b"listen") {
Ok(dup) => {
unsafe { File::from_raw_fd(dup); }
panic!("this is supposed to fail");
},
Err(err) => {
let err = from_syscall_error(err);
assert_eq!(err.kind(), io::ErrorKind::WouldBlock);
}
}
println!("-> Accept would block");
println!("Testing events...");
@@ -73,12 +89,19 @@ fn main() -> io::Result<()> {
println!("--> Thread: Sleeping for 1 second...");
thread::sleep(Duration::from_secs(1));
println!("--> Thread: Writing...");
dup.write(b"hello")?;
dup.flush()?;
client.write(b"hello")?;
client.flush()?;
println!("--> Thread: Sleeping for 1 second...");
thread::sleep(Duration::from_secs(1));
println!("--> Thread: Dropping...");
drop(dup);
drop(client);
println!("--> Thread: Sleeping for 3 seconds...");
thread::sleep(Duration::from_secs(3));
println!("--> Thread: Opening new...");
let mut client = File::open("chan:hello_world")?;
let mut buf = [0; 5];
assert_eq!(client.read(&mut buf)?, 0);
println!("--> Thread: Closing...");
Ok(())
});
@@ -87,45 +110,61 @@ fn main() -> io::Result<()> {
let mut time = syscall::TimeSpec::default();
time_file.read(&mut time)?;
time.tv_sec += 5;
time.tv_sec += 3;
time_file.write(&time)?;
event_file.write(&syscall::Event {
id: client.as_raw_fd(),
id: dup.as_raw_fd(),
flags: syscall::EVENT_READ | syscall::EVENT_WRITE,
data: 0
})?;
event_file.write(&syscall::Event {
id: server.as_raw_fd(),
flags: syscall::EVENT_WRITE | syscall::EVENT_READ,
data: 1
})?;
event_file.write(&syscall::Event {
id: time_file.as_raw_fd(),
flags: syscall::EVENT_READ,
data: 1
data: 2
})?;
let mut event = syscall::Event::default();
event_file.read(&mut event)?;
assert_eq!(event.id, client.as_raw_fd());
assert_eq!(event.id, dup.as_raw_fd());
assert_eq!(event.flags, syscall::EVENT_WRITE);
assert_eq!(event.data, 0);
println!("-> Read event");
for _ in 0..2 {
event_file.read(&mut event)?;
assert_eq!(event.id, client.as_raw_fd());
assert_eq!(event.id, dup.as_raw_fd());
assert_eq!(event.flags, syscall::EVENT_READ);
assert_eq!(event.data, 0);
println!("-> Read event");
client.read(&mut buf)?;
dup.read(&mut buf)?;
}
event_file.read(&mut event)?;
assert_eq!(event.id, time_file.as_raw_fd());
assert_eq!(event.flags, syscall::EVENT_READ);
assert_eq!(event.data, 1);
assert_eq!(event.data, 2);
println!("-> Timed out");
thread.join().unwrap().unwrap();
event_file.read(&mut event)?;
assert_eq!(event.id, server.as_raw_fd());
assert_eq!(event.flags, syscall::EVENT_WRITE);
assert_eq!(event.data, 1);
println!("-> Read accept event");
let dup = syscall::dup(server.as_raw_fd(), b"listen").map_err(from_syscall_error)?;
let dup = unsafe { File::from_raw_fd(dup) };
drop(dup);
thread.join().unwrap()?;
println!("Everything tested!");
+28 -15
View File
@@ -39,17 +39,29 @@ pub struct ChanScheme {
impl ChanScheme {
pub fn post_fevents(&mut self, file: &mut File) -> io::Result<()> {
for (id, handle) in &mut self.handles {
if !handle.notified_write {
handle.notified_write = true;
post_fevent(file, *id, EVENT_WRITE)?;
}
if !handle.buffer.is_empty() || (!handle.is_listener() && handle.remote.is_none()) {
if !handle.notified_read {
handle.notified_read = true;
post_fevent(file, *id, EVENT_READ)?;
if handle.is_listener() {
if handle.remote.is_some() {
// Send writable because that's what smolnetd does for TcpListener
if !handle.notified_write {
handle.notified_write = true;
post_fevent(file, *id, EVENT_WRITE)?;
}
} else {
handle.notified_write = false;
}
} else {
handle.notified_read = false;
if !handle.notified_write {
handle.notified_write = true;
post_fevent(file, *id, EVENT_WRITE)?;
}
if !handle.buffer.is_empty() || handle.remote.is_none() {
if !handle.notified_read {
handle.notified_read = true;
post_fevent(file, *id, EVENT_READ)?;
}
} else {
handle.notified_read = false;
}
}
}
Ok(())
@@ -61,22 +73,23 @@ impl SchemeBlockMut for ChanScheme {
if path.is_empty() {
return Err(Error::new(EPERM));
}
if flags & O_CREAT == O_CREAT && self.listeners.contains_key(path) {
return Err(Error::new(EADDRINUSE));
} else if flags & O_CREAT != O_CREAT && !self.listeners.contains_key(path) {
return Err(Error::new(ENOENT));
}
let mut handle = Handle::default();
handle.flags = flags;
let id = self.next_id;
if flags & O_CREAT == O_CREAT {
if self.listeners.contains_key(path) {
return Err(Error::new(EADDRINUSE));
}
self.listeners.insert(String::from(path), id);
handle.path = Some(String::from(path));
} else {
let listener = self.listeners[path];
let listener = self.listeners.get(path).ok_or(Error::new(ENOENT))?;
let handle = self.handles.get_mut(&listener).expect("orphan listener left over");
if handle.remote.is_some() {
return Err(Error::new(ECONNREFUSED));
}
handle.remote = Some(id);
}
self.handles.insert(id, handle);