fix(detect): unregister device from epoll when removed on Wayland. #836
This commit is contained in:
parent
846d0a2be3
commit
ec7f1772dd
|
@ -2,7 +2,7 @@
|
|||
// https://github.com/xkbcommon/libxkbcommon/blob/master/tools/interactive-evdev.c
|
||||
|
||||
use anyhow::Result;
|
||||
use libc::{input_event, size_t, ssize_t, EWOULDBLOCK, O_CLOEXEC, O_NONBLOCK, O_RDONLY};
|
||||
use libc::{input_event, size_t, ssize_t, ENODEV, EWOULDBLOCK, O_CLOEXEC, O_NONBLOCK, O_RDONLY};
|
||||
use log::trace;
|
||||
use scopeguard::ScopeGuard;
|
||||
use std::collections::HashMap;
|
||||
|
@ -127,7 +127,11 @@ impl Device {
|
|||
}
|
||||
|
||||
if len < 0 && unsafe { *errno_ptr } != EWOULDBLOCK {
|
||||
return Err(DeviceError::BlockingReadOperation().into());
|
||||
if unsafe { *errno_ptr } == ENODEV {
|
||||
return Err(DeviceError::FailedReadNoSuchDevice.into());
|
||||
}
|
||||
|
||||
return Err(DeviceError::FailedRead(unsafe { *errno_ptr }).into());
|
||||
}
|
||||
|
||||
Ok(events)
|
||||
|
@ -322,6 +326,9 @@ pub enum DeviceError {
|
|||
#[error("no devices found")]
|
||||
NoDevicesFound(),
|
||||
|
||||
#[error("read operation can't block device")]
|
||||
BlockingReadOperation(),
|
||||
#[error("read operation failed with code: `{0}`")]
|
||||
FailedRead(i32),
|
||||
|
||||
#[error("read operation failed: ENODEV No such device")]
|
||||
FailedReadNoSuchDevice,
|
||||
}
|
||||
|
|
|
@ -38,8 +38,9 @@ use keymap::Keymap;
|
|||
use lazycell::LazyCell;
|
||||
use libc::{
|
||||
__errno_location, close, epoll_ctl, epoll_event, epoll_wait, EINTR, EPOLLIN, EPOLL_CTL_ADD,
|
||||
EPOLL_CTL_DEL,
|
||||
};
|
||||
use log::{debug, error, info, trace};
|
||||
use log::{debug, error, info, trace, warn};
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::event::{InputEvent, Key, KeyboardEvent, Variant};
|
||||
|
@ -204,7 +205,9 @@ impl Source for EVDEVSource {
|
|||
}
|
||||
}
|
||||
|
||||
for ev in evs.iter() {
|
||||
#[allow(clippy::needless_range_loop)]
|
||||
for i in 0usize..(ret as usize) {
|
||||
let ev = evs[i];
|
||||
let device = &self.devices[ev.u64 as usize];
|
||||
match device.read() {
|
||||
Ok(events) if !events.is_empty() => {
|
||||
|
@ -226,7 +229,30 @@ impl Source for EVDEVSource {
|
|||
});
|
||||
}
|
||||
Ok(_) => { /* SKIP EMPTY */ }
|
||||
Err(err) => error!("Can't read from device {}: {}", device.get_path(), err),
|
||||
Err(err) => {
|
||||
if let Some(DeviceError::FailedReadNoSuchDevice) = err.downcast_ref::<DeviceError>() {
|
||||
warn!("Can't read from device {}, this error usually means the device has been disconnected, removing from epoll.", device.get_path());
|
||||
|
||||
if unsafe {
|
||||
epoll_ctl(
|
||||
*epfd,
|
||||
EPOLL_CTL_DEL,
|
||||
device.get_raw_fd(),
|
||||
std::ptr::null_mut(),
|
||||
)
|
||||
} != 0
|
||||
{
|
||||
error!(
|
||||
"Could not remove {} from epoll, errno {}",
|
||||
device.get_path(),
|
||||
unsafe { *errno_ptr }
|
||||
);
|
||||
return Err(EVDEVSourceError::Internal().into());
|
||||
}
|
||||
} else {
|
||||
error!("Can't read from device {}: {}", device.get_path(), err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user