scheme-utils: Panic on scheme EOF
EOF used to be triggered by unmounting a scheme, but this is no longer the case since namespaces got moved to userspace. Unmounting now only closes the scheme root fd.
This commit is contained in:
+2
-8
@@ -71,16 +71,10 @@ fn daemon(daemon: SchemeDaemon) -> anyhow::Result<()> {
|
||||
let mut readiness = ReadinessBased::new(&socket, 16);
|
||||
|
||||
loop {
|
||||
if !readiness.read_and_process_requests(&mut *scheme.lock().unwrap())? {
|
||||
break;
|
||||
}
|
||||
readiness.read_and_process_requests(&mut *scheme.lock().unwrap())?;
|
||||
readiness.poll_all_requests(&mut *scheme.lock().unwrap())?;
|
||||
if !readiness.write_responses()? {
|
||||
break;
|
||||
};
|
||||
readiness.write_responses()?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
||||
@@ -96,12 +96,9 @@ fn daemon(daemon: daemon::Daemon, pcid_handle: PciFunctionHandle) -> ! {
|
||||
readiness_based
|
||||
.poll_all_requests(&mut device)
|
||||
.expect("ac97d: failed to poll requests");
|
||||
if !readiness_based
|
||||
readiness_based
|
||||
.write_responses()
|
||||
.expect("ac97d: failed to write to socket")
|
||||
{
|
||||
break;
|
||||
}
|
||||
.expect("ac97d: failed to write to socket");
|
||||
|
||||
/*
|
||||
let next_read = device_irq.next_read();
|
||||
@@ -111,18 +108,12 @@ fn daemon(daemon: daemon::Daemon, pcid_handle: PciFunctionHandle) -> ! {
|
||||
*/
|
||||
}
|
||||
Source::Scheme => {
|
||||
if !readiness_based
|
||||
readiness_based
|
||||
.read_and_process_requests(&mut device)
|
||||
.expect("ac97d: failed to read from socket")
|
||||
{
|
||||
break;
|
||||
}
|
||||
if !readiness_based
|
||||
.expect("ac97d: failed to read from socket");
|
||||
readiness_based
|
||||
.write_responses()
|
||||
.expect("ac97d: failed to write to socket")
|
||||
{
|
||||
break;
|
||||
}
|
||||
.expect("ac97d: failed to write to socket");
|
||||
|
||||
/*
|
||||
let next_read = device.borrow().next_read();
|
||||
|
||||
@@ -101,12 +101,9 @@ fn daemon(daemon: daemon::Daemon, mut pcid_handle: PciFunctionHandle) -> ! {
|
||||
readiness_based
|
||||
.poll_all_requests(&mut device)
|
||||
.expect("ihdad: failed to poll requests");
|
||||
if !readiness_based
|
||||
readiness_based
|
||||
.write_responses()
|
||||
.expect("ihdad: failed to write to socket")
|
||||
{
|
||||
break;
|
||||
}
|
||||
.expect("ihdad: failed to write to socket");
|
||||
|
||||
/*
|
||||
let next_read = device_irq.next_read();
|
||||
@@ -116,18 +113,12 @@ fn daemon(daemon: daemon::Daemon, mut pcid_handle: PciFunctionHandle) -> ! {
|
||||
*/
|
||||
}
|
||||
Source::Scheme => {
|
||||
if !readiness_based
|
||||
readiness_based
|
||||
.read_and_process_requests(&mut device)
|
||||
.expect("ihdad: failed to read from socket")
|
||||
{
|
||||
break;
|
||||
}
|
||||
if !readiness_based
|
||||
.expect("ihdad: failed to read from socket");
|
||||
readiness_based
|
||||
.write_responses()
|
||||
.expect("ihdad: failed to write to socket")
|
||||
{
|
||||
break;
|
||||
}
|
||||
.expect("ihdad: failed to write to socket");
|
||||
|
||||
/*
|
||||
let next_read = device.borrow().next_read();
|
||||
|
||||
@@ -87,12 +87,9 @@ fn daemon(daemon: daemon::Daemon) -> ! {
|
||||
readiness_based
|
||||
.poll_all_requests(&mut device)
|
||||
.expect("sb16d: failed to poll requests");
|
||||
if !readiness_based
|
||||
readiness_based
|
||||
.write_responses()
|
||||
.expect("sb16d: failed to write to socket")
|
||||
{
|
||||
break;
|
||||
}
|
||||
.expect("sb16d: failed to write to socket");
|
||||
|
||||
/*
|
||||
let next_read = device_irq.next_read();
|
||||
@@ -102,18 +99,12 @@ fn daemon(daemon: daemon::Daemon) -> ! {
|
||||
*/
|
||||
}
|
||||
Source::Scheme => {
|
||||
if !readiness_based
|
||||
readiness_based
|
||||
.read_and_process_requests(&mut device)
|
||||
.expect("sb16d: failed to read from socket")
|
||||
{
|
||||
break;
|
||||
}
|
||||
if !readiness_based
|
||||
.expect("sb16d: failed to read from socket");
|
||||
readiness_based
|
||||
.write_responses()
|
||||
.expect("sb16d: failed to write to socket")
|
||||
{
|
||||
break;
|
||||
}
|
||||
.expect("sb16d: failed to write to socket");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+13
-67
@@ -75,7 +75,7 @@ fn inner(daemon: daemon::Daemon) -> anyhow::Result<()> {
|
||||
daemon.ready();
|
||||
|
||||
// Create event listener for both files
|
||||
let mut event_queue = EventQueue::<EventSource>::new()
|
||||
let event_queue = EventQueue::<EventSource>::new()
|
||||
.map_err(|e| anyhow::anyhow!("failed to create event queue: {e}"))?;
|
||||
event_queue
|
||||
.subscribe(
|
||||
@@ -108,96 +108,42 @@ fn inner(daemon: daemon::Daemon) -> anyhow::Result<()> {
|
||||
|
||||
libredox::call::setrens(0, 0)?;
|
||||
|
||||
// EOF flags
|
||||
let mut chan_eof = false;
|
||||
let mut shm_eof = false;
|
||||
let mut uds_stream_eof = false;
|
||||
let mut uds_dgram_eof = false;
|
||||
while !(chan_eof && shm_eof && uds_stream_eof && uds_dgram_eof) {
|
||||
let Some(event_res) = event_queue.next() else {
|
||||
break;
|
||||
};
|
||||
let event = event_res.map_err(|e| anyhow::anyhow!("error occured in event queue: {e}"))?;
|
||||
loop {
|
||||
let event = event_queue
|
||||
.next_event()
|
||||
.map_err(|e| anyhow::anyhow!("error occured in event queue: {e}"))?;
|
||||
|
||||
match event.user_data {
|
||||
EventSource::ChanSocket => {
|
||||
// Channel scheme
|
||||
if !chan_eof {
|
||||
// 1. Read and process requests
|
||||
if !chan_handler.read_and_process_requests(&mut chan)? {
|
||||
chan_eof = true;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Poll all blocking requests
|
||||
chan_handler.read_and_process_requests(&mut chan)?;
|
||||
chan_handler
|
||||
.poll_all_requests(&mut chan)
|
||||
.map_err(|e| anyhow::anyhow!("error occured in poll_all_requests: {e}"))?;
|
||||
|
||||
// 3. Write responses
|
||||
// write_responses returns a Result<bool>, but currently only returns true.
|
||||
if !chan_handler.write_responses()? {
|
||||
chan_eof = true;
|
||||
}
|
||||
chan_handler.write_responses()?;
|
||||
}
|
||||
EventSource::ShmSocket => {
|
||||
// Shared memory scheme
|
||||
if !shm_eof {
|
||||
// 1. Read and process requests
|
||||
if !shm_handler.read_and_process_requests(&mut shm)? {
|
||||
shm_eof = true;
|
||||
}
|
||||
}
|
||||
|
||||
shm_handler.read_and_process_requests(&mut shm)?;
|
||||
// shm is not a blocking scheme
|
||||
|
||||
// 2. Write responses
|
||||
// write_responses returns a Result<bool>, but currently only returns true.
|
||||
if !shm_handler.write_responses()? {
|
||||
shm_eof = true;
|
||||
}
|
||||
shm_handler.write_responses()?;
|
||||
}
|
||||
EventSource::UdsStreamSocket => {
|
||||
// Unix Domain Socket Stream scheme
|
||||
if !uds_stream_eof {
|
||||
// 1. Read and process requests
|
||||
if !uds_stream_handler.read_and_process_requests(&mut uds_stream)? {
|
||||
uds_stream_eof = true;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Poll all blocking requests
|
||||
uds_stream_handler.read_and_process_requests(&mut uds_stream)?;
|
||||
uds_stream_handler
|
||||
.poll_all_requests(&mut uds_stream)
|
||||
.map_err(|e| anyhow::anyhow!("error occured in poll_all_requests: {e}"))?;
|
||||
|
||||
// 3. Write responses
|
||||
// write_responses returns a Result<bool>, but currently only returns true.
|
||||
if !uds_stream_handler.write_responses()? {
|
||||
uds_stream_eof = true;
|
||||
}
|
||||
uds_stream_handler.write_responses()?;
|
||||
}
|
||||
EventSource::UdsDgramSocket => {
|
||||
// Unix Domain Socket Dgram scheme
|
||||
if !uds_dgram_eof {
|
||||
// 1. Read and process requests
|
||||
if !uds_dgram_handler.read_and_process_requests(&mut uds_dgram)? {
|
||||
uds_dgram_eof = true;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Poll all blocking requests
|
||||
uds_dgram_handler.read_and_process_requests(&mut uds_dgram)?;
|
||||
uds_dgram_handler
|
||||
.poll_all_requests(&mut uds_dgram)
|
||||
.map_err(|e| anyhow::anyhow!("error occured in poll_all_requests: {e}"))?;
|
||||
|
||||
// 3. Write responses
|
||||
// write_responses returns a Result<bool>, but currently only returns true.
|
||||
if !uds_dgram_handler.write_responses()? {
|
||||
uds_dgram_eof = true;
|
||||
}
|
||||
uds_dgram_handler.write_responses()?;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
+4
-15
@@ -95,26 +95,15 @@ fn scan_requests(
|
||||
handler: &mut ReadinessBased<'_>,
|
||||
scheme: &mut PtyScheme,
|
||||
) -> libredox::error::Result<()> {
|
||||
// 1. Read and process requests
|
||||
if !handler
|
||||
handler
|
||||
.read_and_process_requests(scheme)
|
||||
.expect("pty: failed to read from socket")
|
||||
{
|
||||
panic!("pty: channel EOF")
|
||||
}
|
||||
|
||||
// 2. Poll all blocking requests
|
||||
.expect("pty: failed to read from socket");
|
||||
handler
|
||||
.poll_all_requests(scheme)
|
||||
.expect("pty: error occured in poll_all_requests");
|
||||
|
||||
// 3. Write responses
|
||||
if !handler
|
||||
handler
|
||||
.write_responses()
|
||||
.expect("pty: failed to write to socket")
|
||||
{
|
||||
panic!("pty: channel EOF")
|
||||
}
|
||||
.expect("pty: failed to write to socket");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -31,15 +31,16 @@ impl<'sock> ReadinessBased<'sock> {
|
||||
state: SchemeState::new(),
|
||||
}
|
||||
}
|
||||
pub fn read_and_process_requests(&mut self, scheme: &mut impl SchemeSync) -> Result<bool> {
|
||||
pub fn read_and_process_requests(&mut self, scheme: &mut impl SchemeSync) -> Result<()> {
|
||||
assert!(self.requests_read.is_empty());
|
||||
|
||||
match self
|
||||
.socket
|
||||
.read_requests(&mut self.requests_read, SignalBehavior::Interrupt)
|
||||
{
|
||||
// TODO: write ECANCELED or similar for everything in self.states?
|
||||
Ok(()) if self.requests_read.is_empty() => return Ok(false), // EOF
|
||||
Ok(()) if self.requests_read.is_empty() => {
|
||||
unreachable!("blocking scheme read failed to read anything");
|
||||
}
|
||||
Ok(())
|
||||
| Err(Error {
|
||||
errno: errno::EINTR | errno::EWOULDBLOCK | errno::EAGAIN,
|
||||
@@ -113,7 +114,7 @@ impl<'sock> ReadinessBased<'sock> {
|
||||
self.responses_to_write.push_back(resp);
|
||||
}
|
||||
|
||||
Ok(true)
|
||||
Ok(())
|
||||
}
|
||||
// TODO: Doesn't scale. Instead, provide an API for some form of queue.
|
||||
// TODO: panic if id isn't present?
|
||||
@@ -175,17 +176,18 @@ impl<'sock> ReadinessBased<'sock> {
|
||||
self.ready_queue.extend(self.states.keys().copied());
|
||||
self.poll_ready_requests(scheme)
|
||||
}
|
||||
pub fn write_responses(&mut self) -> Result<bool> {
|
||||
pub fn write_responses(&mut self) -> Result<()> {
|
||||
match self
|
||||
.socket
|
||||
.write_responses(&mut self.responses_to_write, SignalBehavior::Restart)
|
||||
{
|
||||
// TODO: write ECANCELED or similar for everything in self.states?
|
||||
//Ok(()) if !self.responses_to_write.is_empty() => Ok(false), // EOF, FIXME
|
||||
Ok(()) if !self.responses_to_write.is_empty() => {
|
||||
panic!("failed to write all scheme responses");
|
||||
}
|
||||
Ok(())
|
||||
| Err(Error {
|
||||
errno: errno::EINTR | errno::EWOULDBLOCK | errno::EAGAIN,
|
||||
}) => Ok(true),
|
||||
}) => Ok(()),
|
||||
Err(err) => return Err(LError::from(err).into()),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user