kms: Close drm fds via session
This commit is contained in:
parent
cad5ed8945
commit
6eb5ca1f94
2 changed files with 55 additions and 9 deletions
|
|
@ -50,6 +50,7 @@ use std::{
|
||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
collections::{HashMap, HashSet},
|
collections::{HashMap, HashSet},
|
||||||
fmt,
|
fmt,
|
||||||
|
os::fd::OwnedFd,
|
||||||
path::Path,
|
path::Path,
|
||||||
sync::{atomic::AtomicBool, mpsc::Receiver, Arc, RwLock},
|
sync::{atomic::AtomicBool, mpsc::Receiver, Arc, RwLock},
|
||||||
time::Duration,
|
time::Duration,
|
||||||
|
|
@ -486,7 +487,7 @@ impl State {
|
||||||
.with_context(|| format!("Couldn't find drm node for {}", dev))?;
|
.with_context(|| format!("Couldn't find drm node for {}", dev))?;
|
||||||
|
|
||||||
let mut outputs_removed = Vec::new();
|
let mut outputs_removed = Vec::new();
|
||||||
if let Some(mut device) = backend.drm_devices.shift_remove(&drm_node) {
|
let device_fd = if let Some(mut device) = backend.drm_devices.shift_remove(&drm_node) {
|
||||||
if let Some(mut leasing_global) = device.inner.leasing_global.take() {
|
if let Some(mut leasing_global) = device.inner.leasing_global.take() {
|
||||||
leasing_global.disable_global::<State>();
|
leasing_global.disable_global::<State>();
|
||||||
}
|
}
|
||||||
|
|
@ -509,6 +510,10 @@ impl State {
|
||||||
.write()
|
.write()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.take_if(|node| node == &device.inner.render_node);
|
.take_if(|node| node == &device.inner.render_node);
|
||||||
|
|
||||||
|
Some(device.drm.device().device_fd().device_fd())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
};
|
};
|
||||||
self.common
|
self.common
|
||||||
.output_configuration_state
|
.output_configuration_state
|
||||||
|
|
@ -523,6 +528,19 @@ impl State {
|
||||||
}
|
}
|
||||||
|
|
||||||
backend.refresh_used_devices()?;
|
backend.refresh_used_devices()?;
|
||||||
|
|
||||||
|
if let Some(fd) = device_fd {
|
||||||
|
match TryInto::<OwnedFd>::try_into(fd) {
|
||||||
|
Ok(fd) => {
|
||||||
|
if let Err(err) = backend.session.close(fd) {
|
||||||
|
warn!("Failed to close drm device fd: {}", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
warn!(?drm_node, "Unable to close drm device fd cleanly.");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,7 @@ use smithay::{
|
||||||
shm::{shm_format_to_fourcc, with_buffer_contents},
|
shm::{shm_format_to_fourcc, with_buffer_contents},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use tracing::{error, trace, warn};
|
use tracing::{error, info, trace, warn};
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
borrow::{Borrow, BorrowMut},
|
borrow::{Borrow, BorrowMut},
|
||||||
|
|
@ -98,6 +98,7 @@ use std::{
|
||||||
mpsc::{Receiver, SyncSender},
|
mpsc::{Receiver, SyncSender},
|
||||||
Arc, RwLock,
|
Arc, RwLock,
|
||||||
},
|
},
|
||||||
|
thread::JoinHandle,
|
||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -124,6 +125,7 @@ pub struct Surface {
|
||||||
loop_handle: LoopHandle<'static, State>,
|
loop_handle: LoopHandle<'static, State>,
|
||||||
thread_command: Sender<ThreadCommand>,
|
thread_command: Sender<ThreadCommand>,
|
||||||
thread_token: RegistrationToken,
|
thread_token: RegistrationToken,
|
||||||
|
thread: Option<JoinHandle<()>>,
|
||||||
|
|
||||||
dpms: bool,
|
dpms: bool,
|
||||||
}
|
}
|
||||||
|
|
@ -213,9 +215,11 @@ pub enum ThreadCommand {
|
||||||
node: DrmNode,
|
node: DrmNode,
|
||||||
gbm: GbmAllocator<DrmDeviceFd>,
|
gbm: GbmAllocator<DrmDeviceFd>,
|
||||||
egl: EGLContext, // TODO: Option for software rendering
|
egl: EGLContext, // TODO: Option for software rendering
|
||||||
|
sync: SyncSender<()>,
|
||||||
},
|
},
|
||||||
NodeRemoved {
|
NodeRemoved {
|
||||||
node: DrmNode,
|
node: DrmNode,
|
||||||
|
sync: SyncSender<()>,
|
||||||
},
|
},
|
||||||
UpdateMirroring(Option<Output>),
|
UpdateMirroring(Option<Output>),
|
||||||
UpdateScreenFilter(ScreenFilter),
|
UpdateScreenFilter(ScreenFilter),
|
||||||
|
|
@ -262,7 +266,7 @@ impl Surface {
|
||||||
let active_clone = active.clone();
|
let active_clone = active.clone();
|
||||||
let output_clone = output.clone();
|
let output_clone = output.clone();
|
||||||
|
|
||||||
std::thread::Builder::new()
|
let thread = std::thread::Builder::new()
|
||||||
.name(format!("surface-{}", output.name()))
|
.name(format!("surface-{}", output.name()))
|
||||||
.spawn(move || {
|
.spawn(move || {
|
||||||
if let Err(err) = surface_thread(
|
if let Err(err) = surface_thread(
|
||||||
|
|
@ -350,6 +354,7 @@ impl Surface {
|
||||||
loop_handle: evlh.clone(),
|
loop_handle: evlh.clone(),
|
||||||
thread_command: tx,
|
thread_command: tx,
|
||||||
thread_token,
|
thread_token,
|
||||||
|
thread: Some(thread),
|
||||||
dpms: true,
|
dpms: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -364,17 +369,26 @@ impl Surface {
|
||||||
|
|
||||||
pub fn add_node(&mut self, node: DrmNode, gbm: GbmAllocator<DrmDeviceFd>, egl: EGLContext) {
|
pub fn add_node(&mut self, node: DrmNode, gbm: GbmAllocator<DrmDeviceFd>, egl: EGLContext) {
|
||||||
self.known_nodes.insert(node);
|
self.known_nodes.insert(node);
|
||||||
let _ = self
|
let (tx, rx) = std::sync::mpsc::sync_channel(1);
|
||||||
.thread_command
|
let _ = self.thread_command.send(ThreadCommand::NodeAdded {
|
||||||
.send(ThreadCommand::NodeAdded { node, gbm, egl });
|
node,
|
||||||
|
gbm,
|
||||||
|
egl,
|
||||||
|
sync: tx,
|
||||||
|
});
|
||||||
|
let _ = rx.recv();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove_node(&mut self, node: DrmNode) {
|
pub fn remove_node(&mut self, node: DrmNode) {
|
||||||
self.known_nodes.remove(&node);
|
self.known_nodes.remove(&node);
|
||||||
self.feedback.remove(&node);
|
self.feedback.remove(&node);
|
||||||
|
let (tx, rx) = std::sync::mpsc::sync_channel(1);
|
||||||
let _ = self
|
let _ = self
|
||||||
.thread_command
|
.thread_command
|
||||||
.send(ThreadCommand::NodeRemoved { node });
|
.send(ThreadCommand::NodeRemoved { node, sync: tx });
|
||||||
|
// Block so we can be sure the file descriptor is closed
|
||||||
|
// (which is relevant for the udev device_removed callback).
|
||||||
|
let _ = rx.recv();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_vblank(&self, metadata: Option<DrmEventMetadata>) {
|
pub fn on_vblank(&self, metadata: Option<DrmEventMetadata>) {
|
||||||
|
|
@ -460,6 +474,11 @@ impl Drop for Surface {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
let _ = self.thread_command.send(ThreadCommand::End);
|
let _ = self.thread_command.send(ThreadCommand::End);
|
||||||
self.loop_handle.remove(self.thread_token);
|
self.loop_handle.remove(self.thread_token);
|
||||||
|
if let Some(thread) = self.thread.take() {
|
||||||
|
let name = thread.thread().name().unwrap().to_string();
|
||||||
|
let _ = thread.join();
|
||||||
|
info!("Thread {} terminated.", name)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -547,13 +566,20 @@ fn surface_thread(
|
||||||
Event::Msg(ThreadCommand::Resume { compositor }) => {
|
Event::Msg(ThreadCommand::Resume { compositor }) => {
|
||||||
state.resume(compositor);
|
state.resume(compositor);
|
||||||
}
|
}
|
||||||
Event::Msg(ThreadCommand::NodeAdded { node, gbm, egl }) => {
|
Event::Msg(ThreadCommand::NodeAdded {
|
||||||
|
node,
|
||||||
|
gbm,
|
||||||
|
egl,
|
||||||
|
sync,
|
||||||
|
}) => {
|
||||||
if let Err(err) = state.node_added(node, gbm, egl) {
|
if let Err(err) = state.node_added(node, gbm, egl) {
|
||||||
warn!(?err, ?node, "Failed to add node to surface-thread");
|
warn!(?err, ?node, "Failed to add node to surface-thread");
|
||||||
}
|
}
|
||||||
|
let _ = sync.send(());
|
||||||
}
|
}
|
||||||
Event::Msg(ThreadCommand::NodeRemoved { node }) => {
|
Event::Msg(ThreadCommand::NodeRemoved { node, sync }) => {
|
||||||
state.node_removed(node);
|
state.node_removed(node);
|
||||||
|
let _ = sync.send(());
|
||||||
}
|
}
|
||||||
Event::Msg(ThreadCommand::VBlank(metadata)) => {
|
Event::Msg(ThreadCommand::VBlank(metadata)) => {
|
||||||
state.on_vblank(metadata);
|
state.on_vblank(metadata);
|
||||||
|
|
@ -716,6 +742,8 @@ impl SurfaceThreadState {
|
||||||
|
|
||||||
fn node_removed(&mut self, node: DrmNode) {
|
fn node_removed(&mut self, node: DrmNode) {
|
||||||
self.api.as_mut().remove_node(&node);
|
self.api.as_mut().remove_node(&node);
|
||||||
|
// force enumeration
|
||||||
|
let _ = self.api.devices();
|
||||||
//self.software_api.as_mut().remove_node(node);
|
//self.software_api.as_mut().remove_node(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue