backend.libseat: Fix dispatch double borrow

This commit is contained in:
Poly 2021-08-26 01:00:13 +02:00
parent daef0a11df
commit 10cab4eab9
1 changed files with 53 additions and 34 deletions

View File

@ -18,7 +18,10 @@ use std::{
use nix::{errno::Errno, fcntl::OFlag, unistd::close}; 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::{ use crate::{
backend::session::{AsErrno, Session, Signal as SessionSignal}, backend::session::{AsErrno, Session, Signal as SessionSignal},
@ -53,6 +56,7 @@ pub struct LibSeatSession {
pub struct LibSeatSessionNotifier { pub struct LibSeatSessionNotifier {
internal: Rc<LibSeatSessionImpl>, internal: Rc<LibSeatSessionImpl>,
signaler: Signaler<SessionSignal>, signaler: Signaler<SessionSignal>,
rx: Channel<SeatEvent>,
token: Token, token: Token,
} }
@ -65,26 +69,20 @@ impl LibSeatSession {
let logger = crate::slog_or_fallback(logger) let logger = crate::slog_or_fallback(logger)
.new(o!("smithay_module" => "backend_session", "session_type" => "libseat")); .new(o!("smithay_module" => "backend_session", "session_type" => "libseat"));
let active = Arc::new(AtomicBool::new(false)); let (tx, rx) = calloop::channel::channel();
let signaler = Signaler::new();
let seat = { let seat = {
let log = logger.clone(); let log = logger.clone();
let active = active.clone();
let signaler = signaler.clone();
Seat::open( Seat::open(
move |seat, event| match event { move |_seat, event| match event {
SeatEvent::Enable => { SeatEvent::Enable => {
debug!(log, "Enable callback called"); debug!(log, "Enable callback called");
active.store(true, Ordering::SeqCst); tx.send(event).unwrap();
signaler.signal(SessionSignal::ActivateSession);
} }
SeatEvent::Disable => { SeatEvent::Disable => {
debug!(log, "Disable callback called"); debug!(log, "Disable callback called");
active.store(false, Ordering::SeqCst); tx.send(event).unwrap();
signaler.signal(SessionSignal::PauseSession);
seat.disable().unwrap();
} }
}, },
logger.clone(), logger.clone(),
@ -92,30 +90,32 @@ impl LibSeatSession {
}; };
seat.map(|mut seat| { seat.map(|mut seat| {
let seat_name = seat.name().to_owned();
// In some cases enable_seat event is avalible right after startup // In some cases enable_seat event is avalible right after startup
// so, we can dispatch it // so, we can dispatch it
seat.dispatch(0).unwrap(); seat.dispatch(0).unwrap();
let seat_name = seat.name().to_owned();
let internal = Rc::new(LibSeatSessionImpl { let internal = Rc::new(LibSeatSessionImpl {
seat: RefCell::new(seat), seat: RefCell::new(seat),
active, active: Arc::new(AtomicBool::new(false)),
devices: RefCell::new(HashMap::new()), devices: RefCell::new(HashMap::new()),
logger, logger,
}); });
( let session = LibSeatSession {
LibSeatSession {
internal: Rc::downgrade(&internal), internal: Rc::downgrade(&internal),
seat_name, seat_name,
}, };
LibSeatSessionNotifier {
let notifier = LibSeatSessionNotifier {
internal, internal,
signaler, signaler: Signaler::new(),
rx,
token: Token::invalid(), token: Token::invalid(),
}, };
)
(session, notifier)
}) })
.map_err(|err| Error::FailedToOpenSession(Errno::from_i32(err.into()))) .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() { if let Some(session) = self.internal.upgrade() {
debug!(session.logger, "Closing device: {:?}", fd); 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 { let out = if let Some(dev) = dev {
session session
@ -214,17 +214,38 @@ impl EventSource for LibSeatSessionNotifier {
type Metadata = (); type Metadata = ();
type Ret = (); type Ret = ();
fn process_events<F>(&mut self, _readiness: Readiness, token: Token, _: F) -> std::io::Result<PostAction> fn process_events<F>(&mut self, readiness: Readiness, token: Token, _: F) -> std::io::Result<PostAction>
where where
F: FnMut((), &mut ()), F: FnMut((), &mut ()),
{ {
if token == self.token { if token == self.token {
self.internal.seat.borrow_mut().dispatch(0).unwrap(); 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<Seat> is stored in LibSeatSessionNotifier so this is unreachable
}
})
} }
fn register(&mut self, poll: &mut Poll, factory: &mut TokenFactory) -> std::io::Result<()> { fn register(&mut self, poll: &mut Poll, factory: &mut TokenFactory) -> std::io::Result<()> {
self.rx.register(poll, factory)?;
self.token = factory.token(); self.token = factory.token();
poll.register( poll.register(
self.internal.seat.borrow_mut().get_fd().unwrap(), self.internal.seat.borrow_mut().get_fd().unwrap(),
@ -232,11 +253,11 @@ impl EventSource for LibSeatSessionNotifier {
calloop::Mode::Level, calloop::Mode::Level,
self.token, self.token,
) )
.unwrap();
Ok(())
} }
fn reregister(&mut self, poll: &mut Poll, factory: &mut TokenFactory) -> std::io::Result<()> { fn reregister(&mut self, poll: &mut Poll, factory: &mut TokenFactory) -> std::io::Result<()> {
self.rx.reregister(poll, factory)?;
self.token = factory.token(); self.token = factory.token();
poll.reregister( poll.reregister(
self.internal.seat.borrow_mut().get_fd().unwrap(), self.internal.seat.borrow_mut().get_fd().unwrap(),
@ -244,15 +265,13 @@ impl EventSource for LibSeatSessionNotifier {
calloop::Mode::Level, calloop::Mode::Level,
self.token, self.token,
) )
.unwrap();
Ok(())
} }
fn unregister(&mut self, poll: &mut Poll) -> std::io::Result<()> { fn unregister(&mut self, poll: &mut Poll) -> std::io::Result<()> {
self.rx.unregister(poll)?;
self.token = Token::invalid(); self.token = Token::invalid();
poll.unregister(self.internal.seat.borrow_mut().get_fd().unwrap()) poll.unregister(self.internal.seat.borrow_mut().get_fd().unwrap())
.unwrap();
Ok(())
} }
} }