From d360a57f6ef00b5f0e76d33a762adcfc6a85326b Mon Sep 17 00:00:00 2001 From: Nova Date: Sun, 13 Jul 2025 21:26:56 -0700 Subject: [PATCH] fix: wayland lockfile --- Cargo.lock | 2 -- Cargo.toml | 2 -- src/main.rs | 2 +- src/wayland/mod.rs | 34 +++++++++++++++++++--------------- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b67d216..26946cc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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", diff --git a/Cargo.toml b/Cargo.toml index b2567a3..5aed0d2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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 diff --git a/src/main.rs b/src/main.rs index be657ce..ca32613 100644 --- a/src/main.rs +++ b/src/main.rs @@ -190,7 +190,7 @@ async fn main() -> Result { "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({ diff --git a/src/wayland/mod.rs b/src/wayland/mod.rs index 54ad7c4..a697d5e 100644 --- a/src/wayland/mod.rs +++ b/src/wayland/mod.rs @@ -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 for ServerError { } } -pub fn get_free_wayland_socket_path() -> Option { +pub fn get_free_wayland_socket_path() -> Option<(PathBuf, FlockLock)> { // 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 { 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 { } // 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, abort_handle: AbortHandle, } impl Wayland { - pub fn new(socket_path: Option) -> Result { - let socket_path = if let Some(path) = socket_path { - path - } else { + pub fn new() -> Result { + 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();