Open scheme in non-blocking mode and ensure events aren't lost

This commit is contained in:
bjorn3
2024-01-14 21:20:42 +01:00
parent 4f6f4d7267
commit ed69a8ef6d
+110 -78
View File
@@ -1,10 +1,11 @@
use event::EventQueue;
use orbclient::Event;
use std::fs::File;
use std::fs::{File, OpenOptions};
use std::io::{ErrorKind, Read, Write};
use std::os::fd::AsRawFd;
use std::os::unix::fs::OpenOptionsExt;
use std::{env, io, mem, slice};
use syscall::{Packet, SchemeMut, EVENT_READ};
use syscall::{Packet, SchemeMut, EVENT_READ, O_NONBLOCK};
use crate::scheme::{FbconScheme, VtIndex};
@@ -35,7 +36,13 @@ fn inner(daemon: redox_daemon::Daemon, vt_ids: &[usize]) -> ! {
// FIXME listen for resize events from inputd and handle them
let mut socket = File::create(":fbcon").expect("fbcond: failed to create fbcon scheme");
let mut socket = OpenOptions::new()
.write(true)
.create(true)
.truncate(true)
.custom_flags(O_NONBLOCK as i32)
.open(":fbcon")
.expect("fbcond: failed to create fbcon scheme");
event_queue
.subscribe(
socket.as_raw_fd().as_raw_fd() as usize,
@@ -56,19 +63,45 @@ fn inner(daemon: redox_daemon::Daemon, vt_ids: &[usize]) -> ! {
.unwrap();
let mut blocked = Vec::new();
// Handle all events that could have happened before registering with the event queue.
handle_event(
&mut socket,
&mut scheme,
&mut blocked,
VtIndex::SCHEMA_SENTINEL,
);
for vt_i in scheme.vts.keys().copied().collect::<Vec<_>>() {
handle_event(&mut socket, &mut scheme, &mut blocked, vt_i);
}
for event in event_queue {
let event = event.expect("fbcond: failed to read event from event queue");
handle_event(&mut socket, &mut scheme, &mut blocked, event.user_data);
}
match event.user_data {
VtIndex::SCHEMA_SENTINEL => {
std::process::exit(0);
}
fn handle_event(
socket: &mut File,
scheme: &mut FbconScheme,
blocked: &mut Vec<Packet>,
event: VtIndex,
) {
match event {
VtIndex::SCHEMA_SENTINEL => {
loop {
let mut packet = Packet::default();
if socket
.read(&mut packet)
.expect("fbcond: failed to read display scheme")
== 0
{
//TODO: Handle blocked
break;
match socket.read(&mut packet) {
Ok(0) => break,
Err(err) if err.kind() == ErrorKind::WouldBlock => {
break;
}
Ok(_) => {}
Err(err) => {
panic!("fbcond: failed to read display scheme: {err}");
}
}
// If it is a read packet, and there is no data, block it. Otherwise, handle packet
@@ -84,82 +117,81 @@ fn inner(daemon: redox_daemon::Daemon, vt_ids: &[usize]) -> ! {
.expect("fbcond: failed to write display scheme");
}
}
vt_i => {
let vt = scheme.vts.get_mut(&vt_i).unwrap();
}
vt_i => {
let vt = scheme.vts.get_mut(&vt_i).unwrap();
let mut events = [Event::new(); 16];
loop {
match read_to_slice(&mut vt.display.input_handle, &mut events) {
Ok(0) => break,
Err(err) if err.kind() == ErrorKind::WouldBlock => {
break;
}
let mut events = [Event::new(); 16];
loop {
match read_to_slice(&mut vt.display.input_handle, &mut events) {
Ok(0) => break,
Err(err) if err.kind() == ErrorKind::WouldBlock => {
break;
}
Ok(count) => {
let events = &mut events[..count];
for event in events.iter_mut() {
vt.input(event)
}
}
Err(err) => {
panic!("fbcond: Error while reading events: {err}");
Ok(count) => {
let events = &mut events[..count];
for event in events.iter_mut() {
vt.input(event)
}
}
Err(err) => {
panic!("fbcond: Error while reading events: {err}");
}
}
}
}
}
// If there are blocked readers, and data is available, handle them
{
let mut i = 0;
while i < blocked.len() {
if scheme.can_read(blocked[i].b).is_some() {
let mut packet = blocked.remove(i);
scheme.handle(&mut packet);
socket
.write(&packet)
.expect("fbcond: failed to write display scheme");
} else {
i += 1;
}
}
}
for (handle_id, handle) in scheme.handles.iter_mut() {
if !handle.events.contains(EVENT_READ) {
continue;
}
// Can't use scheme.can_read() because we borrow handles as mutable.
// (and because it'd treat O_NONBLOCK sockets differently)
let count = scheme
.vts
.get(&handle.vt_i)
.and_then(|console| console.can_read())
.unwrap_or(0);
if count > 0 {
if !handle.notified_read {
handle.notified_read = true;
let event_packet = Packet {
id: 0,
pid: 0,
uid: 0,
gid: 0,
a: syscall::number::SYS_FEVENT,
b: *handle_id,
c: EVENT_READ.bits(),
d: count,
};
socket
.write(&event_packet)
.expect("fbcond: failed to write display event");
}
// If there are blocked readers, and data is available, handle them
{
let mut i = 0;
while i < blocked.len() {
if scheme.can_read(blocked[i].b).is_some() {
let mut packet = blocked.remove(i);
scheme.handle(&mut packet);
socket
.write(&packet)
.expect("fbcond: failed to write display scheme");
} else {
handle.notified_read = false;
i += 1;
}
}
}
std::process::exit(0);
for (handle_id, handle) in scheme.handles.iter_mut() {
if !handle.events.contains(EVENT_READ) {
continue;
}
// Can't use scheme.can_read() because we borrow handles as mutable.
// (and because it'd treat O_NONBLOCK sockets differently)
let count = scheme
.vts
.get(&handle.vt_i)
.and_then(|console| console.can_read())
.unwrap_or(0);
if count > 0 {
if !handle.notified_read {
handle.notified_read = true;
let event_packet = Packet {
id: 0,
pid: 0,
uid: 0,
gid: 0,
a: syscall::number::SYS_FEVENT,
b: *handle_id,
c: EVENT_READ.bits(),
d: count,
};
socket
.write(&event_packet)
.expect("fbcond: failed to write display event");
}
} else {
handle.notified_read = false;
}
}
}