--- a/src/main.rs +++ b/src/main.rs @@ -24,6 +24,7 @@ use redox_driver_sys::pcid_client::PcidClient; use redox_driver_sys::quirks::PciQuirkFlags; use redox_scheme::{SignalBehavior, Socket}; +use syscall04::error::EBADF; use crate::driver::{DriverError, DriverEvent, GpuDriver, Result}; use crate::drivers::DriverRegistry; @@ -71,11 +72,6 @@ fn run() -> Result<()> { info.location ); - let socket = Socket::create("drm") - .map_err(|e| DriverError::Initialization(format!("failed to register drm scheme: {e}")))?; - info!("redox-drm: registered scheme:drm"); - let (event_tx, event_rx) = mpsc::sync_channel::(8); let irq_driver: Arc = driver.clone(); @@ -108,6 +104,15 @@ fn run() -> Result<()> { } }); + // redox-scheme opens the scheme fd with O_CLOEXEC. On Redox, thread startup can + // invalidate a close-on-exec fd opened before the thread workers exist, which + // showed up as an immediate EBADF from next_request() during QEMU greeter boot. + // Register scheme:drm only after the worker threads are running so the listening + // fd remains stable for compositor clients. + let socket = create_drm_socket()?; + info!("redox-drm: registered scheme:drm"); + loop { let request = match socket.next_request(SignalBehavior::Restart) { Ok(Some(request)) => request, @@ -118,6 +123,10 @@ fn run() -> Result<()> { break; } Err(e) => { + if e.errno == EBADF { + info!("redox-drm: scheme fd closed, exiting"); + break; + } error!("redox-drm: failed to receive scheme request: {}", e); continue; } @@ -145,11 +154,22 @@ fn run() -> Result<()> { }; if let Err(e) = socket.write_response(response, SignalBehavior::Restart) { + if e.errno == EBADF { + info!("redox-drm: scheme fd closed while writing response, exiting"); + break; + } error!("redox-drm: failed to write scheme response: {}", e); } } Ok(()) } +fn create_drm_socket() -> Result { + Socket::create("drm") + .map_err(|e| DriverError::Initialization(format!("failed to register drm scheme: {e}"))) +} + fn select_gpu_from_args() -> Result { let mut args = env::args().skip(1); let parsed = match (args.next(), args.next(), args.next()) {