XWayland: add logging
This commit is contained in:
parent
2d8653d9d7
commit
ff63209a17
|
@ -7,10 +7,10 @@ use nix::errno::Errno;
|
||||||
use nix::sys::socket;
|
use nix::sys::socket;
|
||||||
|
|
||||||
/// Find a free X11 display slot and setup
|
/// Find a free X11 display slot and setup
|
||||||
pub(crate) fn prepare_x11_sockets() -> Result<(X11Lock, [UnixStream; 2]), ()> {
|
pub(crate) fn prepare_x11_sockets(log: ::slog::Logger) -> Result<(X11Lock, [UnixStream; 2]), ()> {
|
||||||
for d in 0..33 {
|
for d in 0..33 {
|
||||||
// if fails, try the next one
|
// if fails, try the next one
|
||||||
if let Ok(lock) = X11Lock::grab(d) {
|
if let Ok(lock) = X11Lock::grab(d, log.clone()) {
|
||||||
// we got a lockfile, try and create the socket
|
// we got a lockfile, try and create the socket
|
||||||
if let Ok(sockets) = open_x11_sockets_for_display(d) {
|
if let Ok(sockets) = open_x11_sockets_for_display(d) {
|
||||||
return Ok((lock, sockets));
|
return Ok((lock, sockets));
|
||||||
|
@ -22,16 +22,15 @@ pub(crate) fn prepare_x11_sockets() -> Result<(X11Lock, [UnixStream; 2]), ()> {
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Remove the X11 sockets for a given display number
|
|
||||||
pub(crate) fn cleanup_x11_sockets(display: u32) {}
|
|
||||||
|
|
||||||
pub(crate) struct X11Lock {
|
pub(crate) struct X11Lock {
|
||||||
display: u32,
|
display: u32,
|
||||||
|
log: ::slog::Logger,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl X11Lock {
|
impl X11Lock {
|
||||||
/// Try to grab a lockfile for given X display number
|
/// Try to grab a lockfile for given X display number
|
||||||
fn grab(display: u32) -> Result<X11Lock, ()> {
|
fn grab(display: u32, log: ::slog::Logger) -> Result<X11Lock, ()> {
|
||||||
|
debug!(log, "Attempting to aquire an X11 display lock"; "D" => display);
|
||||||
let filename = format!("/tmp/.X{}-lock", display);
|
let filename = format!("/tmp/.X{}-lock", display);
|
||||||
let lockfile = ::std::fs::OpenOptions::new()
|
let lockfile = ::std::fs::OpenOptions::new()
|
||||||
.write(true)
|
.write(true)
|
||||||
|
@ -47,11 +46,13 @@ impl X11Lock {
|
||||||
let _ = ::std::fs::remove_file(&filename);
|
let _ = ::std::fs::remove_file(&filename);
|
||||||
return Err(());
|
return Err(());
|
||||||
} else {
|
} else {
|
||||||
|
debug!(log, "X11 lock aquired"; "D" => display);
|
||||||
// we got the lockfile and wrote our pid to it, all is good
|
// we got the lockfile and wrote our pid to it, all is good
|
||||||
return Ok(X11Lock { display });
|
return Ok(X11Lock { display, log });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
|
debug!(log, "Failed to acquire lock"; "D" => display);
|
||||||
// we could not open the file, now we try to read it
|
// we could not open the file, now we try to read it
|
||||||
// and if it contains the pid of a process that no longer
|
// and if it contains the pid of a process that no longer
|
||||||
// exist (so if a previous x server claimed it and did not
|
// exist (so if a previous x server claimed it and did not
|
||||||
|
@ -69,8 +70,13 @@ impl X11Lock {
|
||||||
if let Err(NixError::Sys(Errno::ESRCH)) = ::nix::sys::signal::kill(pid, None) {
|
if let Err(NixError::Sys(Errno::ESRCH)) = ::nix::sys::signal::kill(pid, None) {
|
||||||
// no process whose pid equals the contents of the lockfile exists
|
// no process whose pid equals the contents of the lockfile exists
|
||||||
// remove the lockfile and try grabbing it again
|
// remove the lockfile and try grabbing it again
|
||||||
let _ = ::std::fs::remove_file(filename);
|
if let Ok(()) = ::std::fs::remove_file(filename) {
|
||||||
return X11Lock::grab(display);
|
debug!(log, "Lock was blocked by a defunct X11 server, trying again"; "D" => display);
|
||||||
|
return X11Lock::grab(display, log);
|
||||||
|
} else {
|
||||||
|
// we could not remove the lockfile, abort
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// if we reach here, this lockfile exists and is probably in use, give up
|
// if we reach here, this lockfile exists and is probably in use, give up
|
||||||
return Err(());
|
return Err(());
|
||||||
|
@ -85,15 +91,20 @@ impl X11Lock {
|
||||||
|
|
||||||
impl Drop for X11Lock {
|
impl Drop for X11Lock {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
|
info!(self.log, "Cleaning up X11 lock.");
|
||||||
// Cleanup all the X11 files
|
// Cleanup all the X11 files
|
||||||
let _ = ::std::fs::remove_file(format!("/tmp/.X11-unix/X{}", self.display));
|
if let Err(e) = ::std::fs::remove_file(format!("/tmp/.X11-unix/X{}", self.display)) {
|
||||||
let _ = ::std::fs::remove_file(format!("/tmp/.X{}-lock", self.display));
|
warn!(self.log, "Failed to remove X11 socket"; "error" => format!("{:?}", e));
|
||||||
|
}
|
||||||
|
if let Err(e) = ::std::fs::remove_file(format!("/tmp/.X{}-lock", self.display)) {
|
||||||
|
warn!(self.log, "Failed to remove X11 lockfile"; "error" => format!("{:?}", e));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Open the two unix sockets an X server listens on
|
/// Open the two unix sockets an X server listens on
|
||||||
///
|
///
|
||||||
/// SHould only be done after the associated lockfile is aquired!
|
/// Should only be done after the associated lockfile is aquired!
|
||||||
fn open_x11_sockets_for_display(display: u32) -> NixResult<[UnixStream; 2]> {
|
fn open_x11_sockets_for_display(display: u32) -> NixResult<[UnixStream; 2]> {
|
||||||
let path = format!("/tmp/.X11-unix/X{}", display);
|
let path = format!("/tmp/.X11-unix/X{}", display);
|
||||||
// We know this path is not to long, these unwrap cannot fail
|
// We know this path is not to long, these unwrap cannot fail
|
||||||
|
|
|
@ -66,12 +66,22 @@ pub trait XWindowManager {
|
||||||
|
|
||||||
impl<WM: XWindowManager + 'static> XWayland<WM> {
|
impl<WM: XWindowManager + 'static> XWayland<WM> {
|
||||||
/// Start the XWayland server
|
/// Start the XWayland server
|
||||||
pub fn init(wm: WM, token: LoopToken, display: Rc<RefCell<Display>>) -> Result<XWayland<WM>, ()> {
|
pub fn init<L>(
|
||||||
|
wm: WM,
|
||||||
|
token: LoopToken,
|
||||||
|
display: Rc<RefCell<Display>>,
|
||||||
|
logger: L,
|
||||||
|
) -> Result<XWayland<WM>, ()>
|
||||||
|
where
|
||||||
|
L: Into<Option<::slog::Logger>>,
|
||||||
|
{
|
||||||
|
let log = ::slog_or_stdlog(logger);
|
||||||
let inner = Rc::new(RefCell::new(Inner {
|
let inner = Rc::new(RefCell::new(Inner {
|
||||||
wm,
|
wm,
|
||||||
token,
|
token,
|
||||||
wayland_display: display,
|
wayland_display: display,
|
||||||
instance: None,
|
instance: None,
|
||||||
|
log: log.new(o!("smithay_module" => "XWayland")),
|
||||||
}));
|
}));
|
||||||
launch(&inner)?;
|
launch(&inner)?;
|
||||||
Ok(XWayland { inner })
|
Ok(XWayland { inner })
|
||||||
|
@ -99,6 +109,7 @@ struct Inner<WM: XWindowManager> {
|
||||||
token: LoopToken,
|
token: LoopToken,
|
||||||
wayland_display: Rc<RefCell<Display>>,
|
wayland_display: Rc<RefCell<Display>>,
|
||||||
instance: Option<XWaylandInstance>,
|
instance: Option<XWaylandInstance>,
|
||||||
|
log: ::slog::Logger,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Launch an XWayland server
|
// Launch an XWayland server
|
||||||
|
@ -110,10 +121,12 @@ fn launch<WM: XWindowManager + 'static>(inner: &Rc<RefCell<Inner<WM>>>) -> Resul
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
info!(guard.log, "Starting XWayland");
|
||||||
|
|
||||||
let (x_wm_x11, x_wm_me) = UnixStream::pair().map_err(|_| ())?;
|
let (x_wm_x11, x_wm_me) = UnixStream::pair().map_err(|_| ())?;
|
||||||
let (wl_x11, wl_me) = UnixStream::pair().map_err(|_| ())?;
|
let (wl_x11, wl_me) = UnixStream::pair().map_err(|_| ())?;
|
||||||
|
|
||||||
let (lock, x_fds) = prepare_x11_sockets()?;
|
let (lock, x_fds) = prepare_x11_sockets(guard.log.clone())?;
|
||||||
|
|
||||||
// we have now created all the required sockets
|
// we have now created all the required sockets
|
||||||
|
|
||||||
|
@ -174,20 +187,20 @@ fn launch<WM: XWindowManager + 'static>(inner: &Rc<RefCell<Inner<WM>>>) -> Resul
|
||||||
Ok(x) => match x {},
|
Ok(x) => match x {},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
// well, what can we do ?
|
// well, what can we do ?
|
||||||
eprintln!("[smithay] exec XWayland failed: {:?}", e);
|
error!(guard.log, "exec XWayland failed"; "err" => format!("{:?}", e));
|
||||||
unsafe { ::nix::libc::exit(1) };
|
unsafe { ::nix::libc::exit(1) };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
// well, what can we do ?
|
// well, what can we do ?
|
||||||
eprintln!("[smithay] XWayland second fork failed: {:?}", e);
|
error!(guard.log, "XWayland second fork failed"; "err" => format!("{:?}", e));
|
||||||
unsafe { ::nix::libc::exit(1) };
|
unsafe { ::nix::libc::exit(1) };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("[smithay] XWayland first fork failed: {:?}", e);
|
error!(guard.log, "XWayland first fork failed"; "err" => format!("{:?}", e));
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -209,6 +222,7 @@ impl<WM: XWindowManager> Inner<WM> {
|
||||||
fn shutdown(&mut self) {
|
fn shutdown(&mut self) {
|
||||||
// don't do anything if not running
|
// don't do anything if not running
|
||||||
if let Some(mut instance) = self.instance.take() {
|
if let Some(mut instance) = self.instance.take() {
|
||||||
|
info!(self.log, "Shutting down XWayland.");
|
||||||
self.wm.xwayland_exited();
|
self.wm.xwayland_exited();
|
||||||
// kill the client
|
// kill the client
|
||||||
instance.wayland_client.kill();
|
instance.wayland_client.kill();
|
||||||
|
@ -238,7 +252,13 @@ fn client_destroy<WM: XWindowManager + 'static>(data: *mut ()) {
|
||||||
// restart it, unless we really just started it, if it crashes right
|
// restart it, unless we really just started it, if it crashes right
|
||||||
// at startup there is no point
|
// at startup there is no point
|
||||||
if started_at.map(|t| t.elapsed().as_secs()).unwrap_or(10) > 5 {
|
if started_at.map(|t| t.elapsed().as_secs()).unwrap_or(10) > 5 {
|
||||||
|
warn!(inner.borrow().log, "XWayland crashed, restarting.");
|
||||||
let _ = launch(&inner);
|
let _ = launch(&inner);
|
||||||
|
} else {
|
||||||
|
warn!(
|
||||||
|
inner.borrow().log,
|
||||||
|
"XWayland crashed less than 5 seconds after its startup, not restarting."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -253,7 +273,7 @@ fn xwayland_ready<WM: XWindowManager>(inner: &Rc<RefCell<Inner<WM>>>) {
|
||||||
let pid = instance.child_pid.unwrap();
|
let pid = instance.child_pid.unwrap();
|
||||||
|
|
||||||
// find out if the launch was a success by waiting on the intermediate child
|
// find out if the launch was a success by waiting on the intermediate child
|
||||||
let mut success: bool;
|
let success: bool;
|
||||||
loop {
|
loop {
|
||||||
match wait::waitpid(pid, None) {
|
match wait::waitpid(pid, None) {
|
||||||
Ok(wait::WaitStatus::Exited(_, 0)) => {
|
Ok(wait::WaitStatus::Exited(_, 0)) => {
|
||||||
|
@ -275,6 +295,7 @@ fn xwayland_ready<WM: XWindowManager>(inner: &Rc<RefCell<Inner<WM>>>) {
|
||||||
|
|
||||||
if success {
|
if success {
|
||||||
// signal the WM
|
// signal the WM
|
||||||
|
info!(inner.log, "XWayland is ready, signaling the WM.");
|
||||||
wm.xwayland_ready(
|
wm.xwayland_ready(
|
||||||
instance.wm_fd.take().unwrap(), // This is a bug if None
|
instance.wm_fd.take().unwrap(), // This is a bug if None
|
||||||
instance.wayland_client.clone(),
|
instance.wayland_client.clone(),
|
||||||
|
@ -282,6 +303,11 @@ fn xwayland_ready<WM: XWindowManager>(inner: &Rc<RefCell<Inner<WM>>>) {
|
||||||
|
|
||||||
// setup the environemnt
|
// setup the environemnt
|
||||||
::std::env::set_var("DISPLAY", format!(":{}", instance.display_lock.display()));
|
::std::env::set_var("DISPLAY", format!(":{}", instance.display_lock.display()));
|
||||||
|
} else {
|
||||||
|
error!(
|
||||||
|
inner.log,
|
||||||
|
"XWayland crashed at startup, will not try to restart it."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// in all cases, cleanup
|
// in all cases, cleanup
|
||||||
|
|
Loading…
Reference in New Issue