diff --git a/daemon/src/lib.rs b/daemon/src/lib.rs index 9f507221..a0ba9d88 100644 --- a/daemon/src/lib.rs +++ b/daemon/src/lib.rs @@ -11,12 +11,23 @@ use redox_scheme::Socket; use redox_scheme::scheme::{SchemeAsync, SchemeSync}; unsafe fn get_fd(var: &str) -> RawFd { - let fd: RawFd = std::env::var(var).unwrap().parse().unwrap(); + let fd: RawFd = match std::env::var(var) + .map_err(|e| eprintln!("daemon: env var {var} not set: {e}")) + .ok() + .and_then(|val| { + val.parse() + .map_err(|e| eprintln!("daemon: failed to parse {var} as fd: {e}")) + .ok() + }) { + Some(fd) => fd, + None => return -1, + }; if unsafe { libc::fcntl(fd, libc::F_SETFD, libc::FD_CLOEXEC) } == -1 { - panic!( + eprintln!( "daemon: failed to set CLOEXEC flag for {var} fd: {}", io::Error::last_os_error() ); + return -1; } fd } @@ -51,31 +62,40 @@ impl Daemon { /// Notify the process that the daemon is ready to accept requests. pub fn ready(mut self) { - self.write_pipe.write_all(&[0]).unwrap(); + if let Err(err) = self.write_pipe.write_all(&[0]) { + if err.kind() != io::ErrorKind::BrokenPipe { + eprintln!("daemon::ready write failed: {err}"); + } + } } /// Executes `Command` as a child process. // FIXME remove once the service spawning of hwd and pcid-spawner is moved to init #[deprecated] - pub fn spawn(mut cmd: Command) { - let (mut read_pipe, write_pipe) = io::pipe().unwrap(); + pub fn spawn(mut cmd: Command) -> io::Result<()> { + let (mut read_pipe, write_pipe) = io::pipe().map_err(|err| { + io::Error::new(err.kind(), format!("daemon: failed to create readiness pipe: {err}")) + })?; unsafe { pass_fd(&mut cmd, "INIT_NOTIFY", write_pipe.into()) }; - if let Err(err) = cmd.spawn() { - eprintln!("daemon: failed to execute {cmd:?}: {err}"); - return; - } + cmd.spawn().map_err(|err| { + io::Error::new(err.kind(), format!("failed to execute {cmd:?}: {err}")) + })?; let mut data = [0]; match read_pipe.read_exact(&mut data) { - Ok(()) => {} + Ok(()) => Ok(()), Err(err) if err.kind() == io::ErrorKind::UnexpectedEof => { - eprintln!("daemon: {cmd:?} exited without notifying readiness"); - } - Err(err) => { - eprintln!("daemon: failed to wait for {cmd:?}: {err}"); + Err(io::Error::new( + io::ErrorKind::UnexpectedEof, + format!("{cmd:?} exited without notifying readiness"), + )) } + Err(err) => Err(io::Error::new( + err.kind(), + format!("failed to wait for {cmd:?}: {err}"), + )), } } } diff --git a/drivers/audio/ac97d/src/main.rs b/drivers/audio/ac97d/src/main.rs index ffa8a94b..1ce21cde 100644 --- a/drivers/audio/ac97d/src/main.rs +++ b/drivers/audio/ac97d/src/main.rs @@ -3,6 +3,7 @@ use std::os::unix::io::AsRawFd; use std::usize; use event::{user_data, EventQueue}; +use log::error; use pcid_interface::PciFunctionHandle; use redox_scheme::scheme::register_sync_scheme; use redox_scheme::Socket; @@ -22,13 +23,28 @@ fn daemon(daemon: daemon::Daemon, pcid_handle: PciFunctionHandle) -> ! { let mut name = pci_config.func.name(); name.push_str("_ac97"); - let bar0 = pci_config.func.bars[0].expect_port(); - let bar1 = pci_config.func.bars[1].expect_port(); + let bar0 = match pci_config.func.bars[0].try_port() { + Ok(port) => port, + Err(_) => { + error!("ac97d: invalid BAR0 (not a port BAR)"); + std::process::exit(1); + } + }; + let bar1 = match pci_config.func.bars[1].try_port() { + Ok(port) => port, + Err(_) => { + error!("ac97d: invalid BAR1 (not a port BAR)"); + std::process::exit(1); + } + }; let irq = pci_config .func .legacy_interrupt_line - .expect("ac97d: no legacy interrupts supported"); + .unwrap_or_else(|| { + error!("ac97d: no legacy interrupts supported"); + std::process::exit(1); + }); println!(" + ac97 {}", pci_config.func.display()); @@ -40,13 +56,29 @@ fn daemon(daemon: daemon::Daemon, pcid_handle: PciFunctionHandle) -> ! { common::file_level(), ); - common::acquire_port_io_rights().expect("ac97d: failed to set I/O privilege level to Ring 3"); + if let Err(err) = common::acquire_port_io_rights() { + error!("ac97d: failed to set I/O privilege level to Ring 3: {err}"); + std::process::exit(1); + } let mut irq_file = irq.irq_handle("ac97d"); - let socket = Socket::nonblock().expect("ac97d: failed to create socket"); - let mut device = - unsafe { device::Ac97::new(bar0, bar1).expect("ac97d: failed to allocate device") }; + let socket = match Socket::nonblock() { + Ok(socket) => socket, + Err(err) => { + error!("ac97d: failed to create socket: {err}"); + std::process::exit(1); + } + }; + let mut device = unsafe { + match device::Ac97::new(bar0, bar1) { + Ok(device) => device, + Err(err) => { + error!("ac97d: failed to allocate device: {err}"); + std::process::exit(1); + } + } + }; let mut readiness_based = ReadinessBased::new(&socket, 16); user_data! { @@ -56,49 +88,81 @@ fn daemon(daemon: daemon::Daemon, pcid_handle: PciFunctionHandle) -> ! { } } - let event_queue = EventQueue::::new().expect("ac97d: Could not create event queue."); + let event_queue = match EventQueue::::new() { + Ok(queue) => queue, + Err(err) => { + error!("ac97d: could not create event queue: {err}"); + std::process::exit(1); + } + }; event_queue .subscribe( irq_file.as_raw_fd() as usize, Source::Irq, event::EventFlags::READ, ) - .unwrap(); + .unwrap_or_else(|err| { + error!("ac97d: failed to subscribe IRQ fd: {err}"); + std::process::exit(1); + }); event_queue .subscribe( socket.inner().raw(), Source::Scheme, event::EventFlags::READ, ) - .unwrap(); - - register_sync_scheme(&socket, "audiohw", &mut device) - .expect("ac97d: failed to register audiohw scheme to namespace"); + .unwrap_or_else(|err| { + error!("ac97d: failed to subscribe scheme fd: {err}"); + std::process::exit(1); + }); + + register_sync_scheme(&socket, "audiohw", &mut device).unwrap_or_else(|err| { + error!("ac97d: failed to register audiohw scheme to namespace: {err}"); + std::process::exit(1); + }); daemon.ready(); - libredox::call::setrens(0, 0).expect("ac97d: failed to enter null namespace"); + if let Err(err) = libredox::call::setrens(0, 0) { + error!("ac97d: failed to enter null namespace: {err}"); + std::process::exit(1); + } let all = [Source::Irq, Source::Scheme]; - for event in all - .into_iter() - .chain(event_queue.map(|e| e.expect("ac97d: failed to get next event").user_data)) - { + for event in all.into_iter().chain(event_queue.map(|e| match e { + Ok(event) => event.user_data, + Err(err) => { + error!("ac97d: failed to get next event: {err}"); + std::process::exit(1); + } + })) { match event { Source::Irq => { let mut irq = [0; 8]; - irq_file.read(&mut irq).unwrap(); + if let Err(err) = irq_file.read(&mut irq) { + error!("ac97d: failed to read IRQ file: {err}"); + std::process::exit(1); + } if !device.irq() { continue; } - irq_file.write(&mut irq).unwrap(); + if let Err(err) = irq_file.write(&mut irq) { + error!("ac97d: failed to acknowledge IRQ: {err}"); + std::process::exit(1); + } readiness_based .poll_all_requests(&mut device) - .expect("ac97d: failed to poll requests"); + .unwrap_or_else(|err| { + error!("ac97d: failed to poll requests: {err}"); + std::process::exit(1); + }); readiness_based .write_responses() - .expect("ac97d: failed to write to socket"); + .unwrap_or_else(|err| { + error!("ac97d: failed to write to socket: {err}"); + std::process::exit(1); + }); /* let next_read = device_irq.next_read(); @@ -110,10 +174,16 @@ fn daemon(daemon: daemon::Daemon, pcid_handle: PciFunctionHandle) -> ! { Source::Scheme => { readiness_based .read_and_process_requests(&mut device) - .expect("ac97d: failed to read from socket"); + .unwrap_or_else(|err| { + error!("ac97d: failed to read from socket: {err}"); + std::process::exit(1); + }); readiness_based .write_responses() - .expect("ac97d: failed to write to socket"); + .unwrap_or_else(|err| { + error!("ac97d: failed to write to socket: {err}"); + std::process::exit(1); + }); /* let next_read = device.borrow().next_read(); @@ -125,7 +195,7 @@ fn daemon(daemon: daemon::Daemon, pcid_handle: PciFunctionHandle) -> ! { } } - std::process::exit(0); + std::process::exit(1); } #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] diff --git a/drivers/audio/ihdad/src/main.rs b/drivers/audio/ihdad/src/main.rs index 31a2add7..7b15b322 100755 --- a/drivers/audio/ihdad/src/main.rs +++ b/drivers/audio/ihdad/src/main.rs @@ -38,6 +38,10 @@ fn daemon(daemon: daemon::Daemon, mut pcid_handle: PciFunctionHandle) -> ! { log::info!("IHDA {}", pci_config.func.display()); + if let Err(err) = pci_config.func.bars[0].try_mem() { + log::error!("ihdad: invalid BAR0: {:?}", err); + std::process::exit(1); + } let address = unsafe { pcid_handle.map_bar(0) }.ptr.as_ptr() as usize; let irq_file = pci_allocate_interrupt_vector(&mut pcid_handle, "ihdad"); @@ -53,11 +57,28 @@ fn daemon(daemon: daemon::Daemon, mut pcid_handle: PciFunctionHandle) -> ! { } } - let event_queue = - EventQueue::::new().expect("ihdad: Could not create event queue."); - let socket = Socket::nonblock().expect("ihdad: failed to create socket"); + let event_queue = match EventQueue::::new() { + Ok(queue) => queue, + Err(err) => { + log::error!("ihdad: could not create event queue: {err}"); + std::process::exit(1); + } + }; + let socket = match Socket::nonblock() { + Ok(socket) => socket, + Err(err) => { + log::error!("ihdad: failed to create socket: {err}"); + std::process::exit(1); + } + }; let mut device = unsafe { - hda::IntelHDA::new(address, vend_prod).expect("ihdad: failed to allocate device") + match hda::IntelHDA::new(address, vend_prod) { + Ok(device) => device, + Err(err) => { + log::error!("ihdad: failed to allocate device: {err}"); + std::process::exit(1); + } + } }; let mut readiness_based = ReadinessBased::new(&socket, 16); diff --git a/drivers/graphics/ihdgd/src/main.rs b/drivers/graphics/ihdgd/src/main.rs index a8b6cc60..dc68c6d2 100644 --- a/drivers/graphics/ihdgd/src/main.rs +++ b/drivers/graphics/ihdgd/src/main.rs @@ -29,16 +29,26 @@ fn daemon(daemon: daemon::Daemon, mut pcid_handle: PciFunctionHandle) -> ! { log::info!("IHDG {}", pci_config.func.display()); - let device = Device::new(&mut pcid_handle, &pci_config.func) - .expect("ihdgd: failed to initialize device"); + let device = match Device::new(&mut pcid_handle, &pci_config.func) { + Ok(device) => device, + Err(err) => { + log::error!("ihdgd: failed to initialize device: {err}"); + std::process::exit(1); + } + }; let irq_file = pci_allocate_interrupt_vector(&mut pcid_handle, "ihdgd"); // Needs to be before GraphicsScheme::new to avoid a deadlock due to initnsmgr blocking on // /scheme/event as it is already blocked on opening /scheme/display.ihdg.*. // FIXME change the initnsmgr to not block on openat for the target scheme. - let event_queue: EventQueue = - EventQueue::new().expect("ihdgd: failed to create event queue"); + let event_queue: EventQueue = match EventQueue::new() { + Ok(eq) => eq, + Err(err) => { + log::error!("ihdgd: failed to create event queue: {err}"); + std::process::exit(1); + } + }; let mut scheme = GraphicsScheme::new(device, format!("display.ihdg.{}", name), false); @@ -50,53 +60,69 @@ fn daemon(daemon: daemon::Daemon, mut pcid_handle: PciFunctionHandle) -> ! { } } - event_queue - .subscribe( - scheme.inputd_event_handle().as_raw_fd() as usize, - Source::Input, - event::EventFlags::READ, - ) - .unwrap(); - event_queue - .subscribe( - irq_file.irq_handle().as_raw_fd() as usize, - Source::Irq, - event::EventFlags::READ, - ) - .unwrap(); - event_queue - .subscribe( - scheme.event_handle().raw(), - Source::Scheme, - event::EventFlags::READ, - ) - .unwrap(); - - libredox::call::setrens(0, 0).expect("ihdgd: failed to enter null namespace"); + if let Err(err) = event_queue.subscribe( + scheme.inputd_event_handle().as_raw_fd() as usize, + Source::Input, + event::EventFlags::READ, + ) { + log::error!("ihdgd: failed to subscribe to input events: {err}"); + } + if let Err(err) = event_queue.subscribe( + irq_file.irq_handle().as_raw_fd() as usize, + Source::Irq, + event::EventFlags::READ, + ) { + log::error!("ihdgd: failed to subscribe to IRQ events: {err}"); + } + if let Err(err) = event_queue.subscribe( + scheme.event_handle().raw(), + Source::Scheme, + event::EventFlags::READ, + ) { + log::error!("ihdgd: failed to subscribe to scheme events: {err}"); + } + + if let Err(err) = libredox::call::setrens(0, 0) { + log::error!("ihdgd: failed to enter null namespace: {err}"); + std::process::exit(1); + } daemon.ready(); let all = [Source::Input, Source::Irq, Source::Scheme]; - for event in all - .into_iter() - .chain(event_queue.map(|e| e.expect("ihdgd: failed to get next event").user_data)) - { + for event in all.into_iter().chain( + event_queue.filter_map(|e| match e { + Ok(event) => Some(event.user_data), + Err(err) => { + log::error!("ihdgd: failed to get next event: {err}"); + None + } + }), + ) { match event { Source::Input => scheme.handle_vt_events(), Source::Irq => { let mut irq = [0; 8]; - irq_file.irq_handle().read(&mut irq).unwrap(); + if irq_file.irq_handle().read(&mut irq).is_err() { + log::error!("ihdgd: failed to read IRQ"); + continue; + } if scheme.adapter_mut().handle_irq() { - irq_file.irq_handle().write(&mut irq).unwrap(); + if let Err(err) = irq_file.irq_handle().write(&mut irq) { + log::error!("ihdgd: failed to write IRQ: {err}"); + continue; + } scheme.adapter_mut().handle_events(); - scheme.tick().unwrap(); + if let Err(err) = scheme.tick() { + log::error!("ihdgd: failed to handle display events after IRQ: {err}"); + } } } Source::Scheme => { - scheme - .tick() - .expect("ihdgd: failed to handle scheme events"); + if let Err(err) = scheme.tick() { + log::error!("ihdgd: failed to handle scheme events: {err}"); + } } } } diff --git a/drivers/pcid/src/driver_interface/bar.rs b/drivers/pcid/src/driver_interface/bar.rs index b2c1d35b..5005fa32 100644 --- a/drivers/pcid/src/driver_interface/bar.rs +++ b/drivers/pcid/src/driver_interface/bar.rs @@ -29,27 +29,33 @@ impl PciBar { } } - pub fn expect_port(&self) -> u16 { + pub fn try_port(&self) -> Result { match *self { - PciBar::Port(port) => port, - PciBar::Memory32 { .. } | PciBar::Memory64 { .. } => { - panic!("expected port BAR, found memory BAR"); - } - PciBar::None => panic!("expected BAR to exist"), + PciBar::Port(port) => Ok(port), + PciBar::Memory32 { .. } | PciBar::Memory64 { .. } => Err(()), + PciBar::None => Err(()), } } - pub fn expect_mem(&self) -> (usize, usize) { + pub fn try_mem(&self) -> Result<(usize, usize), ()> { match *self { - PciBar::Memory32 { addr, size } => (addr as usize, size as usize), - PciBar::Memory64 { addr, size } => ( + PciBar::Memory32 { addr, size } => Ok((addr as usize, size as usize)), + PciBar::Memory64 { addr, size } => Ok(( addr.try_into() .expect("conversion from 64bit BAR to usize failed"), size.try_into() .expect("conversion from 64bit BAR size to usize failed"), - ), - PciBar::Port(_) => panic!("expected memory BAR, found port BAR"), - PciBar::None => panic!("expected BAR to exist"), + )), + PciBar::Port(_) => Err(()), + PciBar::None => Err(()), } } + + pub fn expect_port(&self) -> u16 { + self.try_port().expect("expected port BAR") + } + + pub fn expect_mem(&self) -> (usize, usize) { + self.try_mem().expect("expected memory BAR") + } }