fix: wayland lockfile
This commit is contained in:
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -5374,12 +5374,10 @@ dependencies = [
|
||||
"global_counter",
|
||||
"input-event-codes",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"memfd",
|
||||
"memmap2",
|
||||
"mint",
|
||||
"nanoid",
|
||||
"nix 0.30.1",
|
||||
"openxr",
|
||||
"parking_lot 0.12.4",
|
||||
"rand",
|
||||
|
||||
@@ -139,8 +139,6 @@ tokio-stream = { version = "0.1.17", optional = true }
|
||||
memmap2 = { version = "0.9.5", optional = true }
|
||||
drm-fourcc = { version = "2.2.0", optional = true }
|
||||
memfd = { version = "0.6.4", optional = true }
|
||||
libc = "0.2.172"
|
||||
nix = "0.30.1"
|
||||
|
||||
[dependencies.stardust-xr]
|
||||
workspace = true
|
||||
|
||||
@@ -190,7 +190,7 @@ async fn main() -> Result<AppExit, JoinError> {
|
||||
"Couldn't make the object registry to find all objects with given interfaces in d-bus",
|
||||
);
|
||||
|
||||
let _wayland = Wayland::new(None).expect("Couldn't create Wayland instance");
|
||||
let _wayland = Wayland::new().expect("Couldn't create Wayland instance");
|
||||
|
||||
let ready_notifier = Arc::new(Notify::new());
|
||||
let io_loop = tokio::task::spawn_blocking({
|
||||
|
||||
@@ -19,7 +19,7 @@ use bevy::render::renderer::RenderDevice;
|
||||
use bevy::render::{Render, RenderApp};
|
||||
use bevy::{asset::Assets, ecs::resource::Resource, image::Image};
|
||||
use bevy_dmabuf::import::ImportedDmatexs;
|
||||
use cluFlock::ToFlock;
|
||||
use cluFlock::{FlockLock, ToFlock};
|
||||
use core::{
|
||||
buffer::{Buffer, WL_BUFFER_REGISTRY},
|
||||
callback::Callback,
|
||||
@@ -27,6 +27,7 @@ use core::{
|
||||
surface::WL_SURFACE_REGISTRY,
|
||||
};
|
||||
use mint::Vector2;
|
||||
use std::fs::File;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::{
|
||||
fs::{self, OpenOptions},
|
||||
@@ -58,7 +59,7 @@ impl From<waynest::server::Error> for ServerError {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_free_wayland_socket_path() -> Option<PathBuf> {
|
||||
pub fn get_free_wayland_socket_path() -> Option<(PathBuf, FlockLock<File>)> {
|
||||
// Use XDG runtime directory for secure, user-specific sockets
|
||||
let base_dirs = directories::BaseDirs::new()?;
|
||||
let runtime_dir = base_dirs.runtime_dir()?;
|
||||
@@ -69,19 +70,21 @@ pub fn get_free_wayland_socket_path() -> Option<PathBuf> {
|
||||
let socket_lock_path = runtime_dir.join(format!("wayland-{display}.lock"));
|
||||
|
||||
// Open lock file without truncation to preserve existing locks
|
||||
let mut _lock = OpenOptions::new()
|
||||
let Ok(lock) = OpenOptions::new()
|
||||
.create(true)
|
||||
.truncate(false) // Prevent destroying other processes' locks
|
||||
.read(true)
|
||||
.write(true)
|
||||
.mode(0o660) // Match Wayland-compositor permissions
|
||||
.open(&socket_lock_path)
|
||||
.ok()?;
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
|
||||
// Atomic mutual exclusion: fail if another process holds the lock
|
||||
if _lock.try_exclusive_lock().is_err() {
|
||||
// Atomic mutual exclusion: fail if another process holds the lock\
|
||||
let Ok(lock) = lock.try_exclusive_lock() else {
|
||||
continue; // Lock held by active compositor
|
||||
}
|
||||
};
|
||||
|
||||
// Check for zombie sockets (file exists but nothing listening)
|
||||
if socket_path.exists() {
|
||||
@@ -96,7 +99,7 @@ pub fn get_free_wayland_socket_path() -> Option<PathBuf> {
|
||||
}
|
||||
|
||||
// Found viable candidate: lock held, socket cleared/available
|
||||
return Some(socket_path);
|
||||
return Some((socket_path, lock));
|
||||
}
|
||||
|
||||
None // Exhausted all conventional display numbers
|
||||
@@ -233,17 +236,15 @@ impl Drop for WaylandClient {
|
||||
|
||||
#[derive(Debug, Resource)]
|
||||
pub struct Wayland {
|
||||
lockfile: FlockLock<File>,
|
||||
abort_handle: AbortHandle,
|
||||
}
|
||||
impl Wayland {
|
||||
pub fn new(socket_path: Option<PathBuf>) -> Result<Self> {
|
||||
let socket_path = if let Some(path) = socket_path {
|
||||
path
|
||||
} else {
|
||||
pub fn new() -> Result<Self> {
|
||||
let (socket_path, lockfile) =
|
||||
get_free_wayland_socket_path().ok_or(ServerError::WaylandError(
|
||||
waynest::server::Error::IoError(std::io::ErrorKind::AddrNotAvailable.into()),
|
||||
))?
|
||||
};
|
||||
))?;
|
||||
|
||||
let _ = WAYLAND_DISPLAY.set(socket_path.clone());
|
||||
|
||||
@@ -253,7 +254,10 @@ impl Wayland {
|
||||
let abort_handle =
|
||||
task::new(|| "wayland loop", Self::handle_wayland_loop(listener))?.abort_handle();
|
||||
|
||||
Ok(Self { abort_handle })
|
||||
Ok(Self {
|
||||
lockfile,
|
||||
abort_handle,
|
||||
})
|
||||
}
|
||||
async fn handle_wayland_loop(mut listener: server::Listener) -> Result<()> {
|
||||
let mut clients = Vec::new();
|
||||
|
||||
Reference in New Issue
Block a user