fix: wayland lockfile

This commit is contained in:
Nova
2025-07-13 21:26:56 -07:00
parent 58328cd63b
commit d360a57f6e
4 changed files with 20 additions and 20 deletions

2
Cargo.lock generated
View File

@@ -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",

View File

@@ -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

View File

@@ -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({

View File

@@ -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();