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