diff --git a/fbcond/src/main.rs b/fbcond/src/main.rs index 5349f038e2..cd0a859810 100644 --- a/fbcond/src/main.rs +++ b/fbcond/src/main.rs @@ -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::>() { + 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, + 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; + } + } }