From 10cab4eab9c5c821d850e743bbc82894dd4d4568 Mon Sep 17 00:00:00 2001 From: Poly Date: Thu, 26 Aug 2021 01:00:13 +0200 Subject: [PATCH] backend.libseat: Fix dispatch double borrow --- src/backend/session/libseat.rs | 87 +++++++++++++++++++++------------- 1 file changed, 53 insertions(+), 34 deletions(-) diff --git a/src/backend/session/libseat.rs b/src/backend/session/libseat.rs index 16a8b61..38e4feb 100644 --- a/src/backend/session/libseat.rs +++ b/src/backend/session/libseat.rs @@ -18,7 +18,10 @@ use std::{ use nix::{errno::Errno, fcntl::OFlag, unistd::close}; -use calloop::{EventSource, Poll, PostAction, Readiness, Token, TokenFactory}; +use calloop::{ + channel::{self, Channel}, + EventSource, Poll, PostAction, Readiness, Token, TokenFactory, +}; use crate::{ backend::session::{AsErrno, Session, Signal as SessionSignal}, @@ -53,6 +56,7 @@ pub struct LibSeatSession { pub struct LibSeatSessionNotifier { internal: Rc, signaler: Signaler, + rx: Channel, token: Token, } @@ -65,26 +69,20 @@ impl LibSeatSession { let logger = crate::slog_or_fallback(logger) .new(o!("smithay_module" => "backend_session", "session_type" => "libseat")); - let active = Arc::new(AtomicBool::new(false)); - let signaler = Signaler::new(); + let (tx, rx) = calloop::channel::channel(); let seat = { let log = logger.clone(); - let active = active.clone(); - let signaler = signaler.clone(); Seat::open( - move |seat, event| match event { + move |_seat, event| match event { SeatEvent::Enable => { debug!(log, "Enable callback called"); - active.store(true, Ordering::SeqCst); - signaler.signal(SessionSignal::ActivateSession); + tx.send(event).unwrap(); } SeatEvent::Disable => { debug!(log, "Disable callback called"); - active.store(false, Ordering::SeqCst); - signaler.signal(SessionSignal::PauseSession); - seat.disable().unwrap(); + tx.send(event).unwrap(); } }, logger.clone(), @@ -92,30 +90,32 @@ impl LibSeatSession { }; seat.map(|mut seat| { + let seat_name = seat.name().to_owned(); + // In some cases enable_seat event is avalible right after startup // so, we can dispatch it seat.dispatch(0).unwrap(); - let seat_name = seat.name().to_owned(); - let internal = Rc::new(LibSeatSessionImpl { seat: RefCell::new(seat), - active, + active: Arc::new(AtomicBool::new(false)), devices: RefCell::new(HashMap::new()), logger, }); - ( - LibSeatSession { - internal: Rc::downgrade(&internal), - seat_name, - }, - LibSeatSessionNotifier { - internal, - signaler, - token: Token::invalid(), - }, - ) + let session = LibSeatSession { + internal: Rc::downgrade(&internal), + seat_name, + }; + + let notifier = LibSeatSessionNotifier { + internal, + signaler: Signaler::new(), + rx, + token: Token::invalid(), + }; + + (session, notifier) }) .map_err(|err| Error::FailedToOpenSession(Errno::from_i32(err.into()))) } @@ -146,7 +146,7 @@ impl Session for LibSeatSession { if let Some(session) = self.internal.upgrade() { debug!(session.logger, "Closing device: {:?}", fd); - let dev = session.devices.borrow().get(&fd).map(|fd| *fd); + let dev = session.devices.borrow().get(&fd).copied(); let out = if let Some(dev) = dev { session @@ -214,17 +214,38 @@ impl EventSource for LibSeatSessionNotifier { type Metadata = (); type Ret = (); - fn process_events(&mut self, _readiness: Readiness, token: Token, _: F) -> std::io::Result + fn process_events(&mut self, readiness: Readiness, token: Token, _: F) -> std::io::Result where F: FnMut((), &mut ()), { if token == self.token { self.internal.seat.borrow_mut().dispatch(0).unwrap(); } - Ok(PostAction::Continue) + + let internal = &self.internal; + let signaler = &self.signaler; + + self.rx.process_events(readiness, token, |event, _| match event { + channel::Event::Msg(event) => match event { + SeatEvent::Enable => { + internal.active.store(true, Ordering::SeqCst); + signaler.signal(SessionSignal::ActivateSession); + } + SeatEvent::Disable => { + internal.active.store(false, Ordering::SeqCst); + signaler.signal(SessionSignal::PauseSession); + internal.seat.borrow_mut().disable().unwrap(); + } + }, + channel::Event::Closed => { + // Tx is stored inside of Seat, and Rc is stored in LibSeatSessionNotifier so this is unreachable + } + }) } fn register(&mut self, poll: &mut Poll, factory: &mut TokenFactory) -> std::io::Result<()> { + self.rx.register(poll, factory)?; + self.token = factory.token(); poll.register( self.internal.seat.borrow_mut().get_fd().unwrap(), @@ -232,11 +253,11 @@ impl EventSource for LibSeatSessionNotifier { calloop::Mode::Level, self.token, ) - .unwrap(); - Ok(()) } fn reregister(&mut self, poll: &mut Poll, factory: &mut TokenFactory) -> std::io::Result<()> { + self.rx.reregister(poll, factory)?; + self.token = factory.token(); poll.reregister( self.internal.seat.borrow_mut().get_fd().unwrap(), @@ -244,15 +265,13 @@ impl EventSource for LibSeatSessionNotifier { calloop::Mode::Level, self.token, ) - .unwrap(); - Ok(()) } fn unregister(&mut self, poll: &mut Poll) -> std::io::Result<()> { + self.rx.unregister(poll)?; + self.token = Token::invalid(); poll.unregister(self.internal.seat.borrow_mut().get_fd().unwrap()) - .unwrap(); - Ok(()) } }