From da7bcf89d400db54bb0a1b158f5a02a4228f4b56 Mon Sep 17 00:00:00 2001 From: fufesou Date: Fri, 6 Oct 2023 21:31:37 +0800 Subject: [PATCH 1/4] fix, wayland --server, envs Signed-off-by: fufesou --- src/platform/linux.rs | 110 +++++++++++++++++++++++++++++---------- src/server/connection.rs | 6 ++- 2 files changed, 88 insertions(+), 28 deletions(-) diff --git a/src/platform/linux.rs b/src/platform/linux.rs index de8c9d732..8ab7693b0 100644 --- a/src/platform/linux.rs +++ b/src/platform/linux.rs @@ -14,6 +14,7 @@ use hbb_common::{ }; use std::{ cell::RefCell, + ffi::OsStr, io::Write, path::{Path, PathBuf}, process::{Child, Command}, @@ -195,17 +196,29 @@ fn start_uinput_service() { } #[inline] -fn try_start_server_(user: Option<(String, String)>) -> ResultType> { - if user.is_some() { - run_as_user(vec!["--server"], user) - } else { - Ok(Some(crate::run_me(vec!["--server"])?)) +fn try_start_server_(desktop: Option<&Desktop>) -> ResultType> { + match desktop { + Some(desktop) => { + let mut envs = vec![]; + if !desktop.display.is_empty() { + envs.push(("DISPLAY", desktop.display.clone())); + } + if !desktop.xauth.is_empty() { + envs.push(("XAUTHORITY", desktop.xauth.clone())); + } + run_as_user( + vec!["--server"], + Some((desktop.uid.clone(), desktop.username.clone())), + envs, + ) + } + None => Ok(Some(crate::run_me(vec!["--server"])?)), } } #[inline] -fn start_server(user: Option<(String, String)>, server: &mut Option) { - match try_start_server_(user) { +fn start_server(desktop: Option<&Desktop>, server: &mut Option) { + match try_start_server_(desktop) { Ok(ps) => *server = ps, Err(err) => { log::error!("Failed to start server: {}", err); @@ -257,6 +270,7 @@ fn stop_subprocess() { fn should_start_server( try_x11: bool, + is_display_changed: bool, uid: &mut String, desktop: &Desktop, cm0: &mut bool, @@ -273,7 +287,7 @@ fn should_start_server( *uid = "".to_owned(); should_kill = true; } - } else if desktop.uid != *uid && !desktop.uid.is_empty() { + } else if is_display_changed || desktop.uid != *uid && !desktop.uid.is_empty() { *uid = desktop.uid.clone(); if try_x11 { set_x11_env(&desktop); @@ -335,6 +349,7 @@ pub fn start_os_service() { let running = Arc::new(AtomicBool::new(true)); let r = running.clone(); + let (mut display, mut xauth): (String, String) = ("".to_owned(), "".to_owned()); let mut desktop = Desktop::default(); let mut sid = "".to_owned(); let mut uid = "".to_owned(); @@ -357,8 +372,10 @@ pub fn start_os_service() { // try kill subprocess "--server" stop_server(&mut user_server); // try start subprocess "--server" + // No need to check is_display_changed here. if should_start_server( true, + false, &mut uid, &desktop, &mut cm0, @@ -373,9 +390,14 @@ pub fn start_os_service() { // try kill subprocess "--server" stop_server(&mut server); + let is_display_changed = desktop.display != display || desktop.xauth != xauth; + display = desktop.display.clone(); + xauth = desktop.xauth.clone(); + // try start subprocess "--server" if should_start_server( false, + is_display_changed, &mut uid, &desktop, &mut cm0, @@ -384,10 +406,7 @@ pub fn start_os_service() { ) { stop_subprocess(); force_stop_server(); - start_server( - Some((desktop.uid.clone(), desktop.username.clone())), - &mut user_server, - ); + start_server(Some(&desktop), &mut user_server); } } else { force_stop_server(); @@ -541,7 +560,16 @@ fn is_opensuse() -> bool { false } -pub fn run_as_user(arg: Vec<&str>, user: Option<(String, String)>) -> ResultType> { +pub fn run_as_user( + arg: Vec<&str>, + user: Option<(String, String)>, + envs: I, +) -> ResultType> +where + I: IntoIterator, + K: AsRef, + V: AsRef, +{ let (uid, username) = match user { Some(id_name) => id_name, None => get_active_user_id_name(), @@ -558,7 +586,7 @@ pub fn run_as_user(arg: Vec<&str>, user: Option<(String, String)>) -> ResultType args.insert(0, "-E"); } - let task = Command::new("sudo").args(args).spawn()?; + let task = Command::new("sudo").envs(envs).args(args).spawn()?; Ok(Some(task)) } @@ -652,7 +680,7 @@ pub(super) fn get_env_tries(name: &str, uid: &str, process: &str, n: usize) -> S #[inline] fn get_env(name: &str, uid: &str, process: &str) -> String { - let cmd = format!("ps -u {} -f | grep '{}' | grep -v 'grep' | tail -1 | awk '{{print $2}}' | xargs -I__ cat /proc/__/environ 2>/dev/null | tr '\\0' '\\n' | grep '^{}=' | tail -1 | sed 's/{}=//g'", uid, process, name, name); + let cmd = format!("ps -u {} -f | grep -E '{}' | grep -v 'grep' | tail -1 | awk '{{print $2}}' | xargs -I__ cat /proc/__/environ 2>/dev/null | tr '\\0' '\\n' | grep '^{}=' | tail -1 | sed 's/{}=//g'", uid, process, name, name); if let Ok(x) = run_cmds(&cmd) { x.trim_end().to_string() } else { @@ -887,9 +915,11 @@ mod desktop { use super::*; pub const XFCE4_PANEL: &str = "xfce4-panel"; - pub const GNOME_SESSION_BINARY: &str = "gnome-session-binary"; pub const SDDM_GREETER: &str = "sddm-greeter"; - pub const PLASMA_X11: &str = "startplasma-x11"; + + const PLASMA_KDED5: &str = "kded5"; + const GNOME_GOA_DAEMON: &str = "goa-daemon"; + const RUSTDESK_TRAY: &str = "rustdesk +--tray"; #[derive(Debug, Clone, Default)] pub struct Desktop { @@ -918,10 +948,30 @@ mod desktop { self.sid.is_empty() || self.is_rustdesk_subprocess } - fn get_display(&mut self) { - let display_envs = vec![GNOME_SESSION_BINARY, XFCE4_PANEL, SDDM_GREETER, PLASMA_X11]; - for diplay_env in display_envs { - self.display = get_env_tries("DISPLAY", &self.uid, diplay_env, 10); + fn get_display_wayland(&mut self) { + let display_proc = vec![PLASMA_KDED5, GNOME_GOA_DAEMON, RUSTDESK_TRAY]; + for proc in display_proc { + self.display = get_env("DISPLAY", &self.uid, proc); + if !self.display.is_empty() { + break; + } + } + } + + fn get_xauth_wayland(&mut self) { + let display_proc = vec![PLASMA_KDED5, GNOME_GOA_DAEMON, RUSTDESK_TRAY]; + for proc in display_proc { + self.xauth = get_env("XAUTHORITY", &self.uid, proc); + if !self.xauth.is_empty() { + break; + } + } + } + + fn get_display_x11(&mut self) { + let display_envs = vec![PLASMA_KDED5, GNOME_GOA_DAEMON, XFCE4_PANEL, SDDM_GREETER]; + for display_env in display_envs { + self.display = get_env_tries("DISPLAY", &self.uid, display_env, 10); if !self.display.is_empty() { break; } @@ -980,9 +1030,9 @@ mod desktop { } } - fn get_xauth(&mut self) { + fn get_xauth_x11(&mut self) { // try by direct access to window manager process by name - let display_envs = vec![GNOME_SESSION_BINARY, XFCE4_PANEL, SDDM_GREETER, PLASMA_X11]; + let display_envs = vec![PLASMA_KDED5, GNOME_GOA_DAEMON, XFCE4_PANEL, SDDM_GREETER]; for diplay_env in display_envs { self.xauth = get_env_tries("XAUTHORITY", &self.uid, diplay_env, 10); if !self.xauth.is_empty() { @@ -1088,16 +1138,22 @@ mod desktop { self.uid = seat0_values[1].clone(); self.username = seat0_values[2].clone(); self.protocal = get_display_server_of_session(&self.sid).into(); - if self.is_wayland() { + if self.is_login_wayland() { self.display = "".to_owned(); self.xauth = "".to_owned(); self.is_rustdesk_subprocess = false; return; } - self.get_display(); - self.get_xauth(); - self.set_is_subprocess(); + if self.is_wayland() { + self.get_display_wayland(); + self.get_xauth_wayland(); + self.is_rustdesk_subprocess = false; + } else { + self.get_display_x11(); + self.get_xauth_x11(); + self.set_is_subprocess(); + } } } } diff --git a/src/server/connection.rs b/src/server/connection.rs index 35538a85a..7da5e4086 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -2522,7 +2522,11 @@ async fn start_ipc( #[cfg(target_os = "linux")] { log::debug!("Start cm"); - res = crate::platform::run_as_user(args.clone(), user.clone()); + res = crate::platform::run_as_user( + args.clone(), + user.clone(), + None::<(&str, &str)>, + ); } if res.is_ok() { break; From b7a4c0664b950b75190dd0d4796a2a3bcec51408 Mon Sep 17 00:00:00 2001 From: fufesou Date: Fri, 6 Oct 2023 23:34:40 +0800 Subject: [PATCH 2/4] fix, wayland --server, display env, better way to find the envs Signed-off-by: fufesou --- src/platform/linux.rs | 84 +++++++++++++++++++++++-------------------- 1 file changed, 45 insertions(+), 39 deletions(-) diff --git a/src/platform/linux.rs b/src/platform/linux.rs index 8ab7693b0..3a140051c 100644 --- a/src/platform/linux.rs +++ b/src/platform/linux.rs @@ -667,17 +667,6 @@ pub fn is_installed() -> bool { } } -pub(super) fn get_env_tries(name: &str, uid: &str, process: &str, n: usize) -> String { - for _ in 0..n { - let x = get_env(name, uid, process); - if !x.is_empty() { - return x; - } - sleep_millis(300); - } - "".to_owned() -} - #[inline] fn get_env(name: &str, uid: &str, process: &str) -> String { let cmd = format!("ps -u {} -f | grep -E '{}' | grep -v 'grep' | tail -1 | awk '{{print $2}}' | xargs -I__ cat /proc/__/environ 2>/dev/null | tr '\\0' '\\n' | grep '^{}=' | tail -1 | sed 's/{}=//g'", uid, process, name, name); @@ -917,6 +906,7 @@ mod desktop { pub const XFCE4_PANEL: &str = "xfce4-panel"; pub const SDDM_GREETER: &str = "sddm-greeter"; + const IBUS_DAEMON: &str = "ibus-daemon"; const PLASMA_KDED5: &str = "kded5"; const GNOME_GOA_DAEMON: &str = "goa-daemon"; const RUSTDESK_TRAY: &str = "rustdesk +--tray"; @@ -948,33 +938,36 @@ mod desktop { self.sid.is_empty() || self.is_rustdesk_subprocess } - fn get_display_wayland(&mut self) { - let display_proc = vec![PLASMA_KDED5, GNOME_GOA_DAEMON, RUSTDESK_TRAY]; - for proc in display_proc { - self.display = get_env("DISPLAY", &self.uid, proc); - if !self.display.is_empty() { - break; - } - } - } - - fn get_xauth_wayland(&mut self) { - let display_proc = vec![PLASMA_KDED5, GNOME_GOA_DAEMON, RUSTDESK_TRAY]; - for proc in display_proc { - self.xauth = get_env("XAUTHORITY", &self.uid, proc); - if !self.xauth.is_empty() { - break; + fn get_display_xauth_wayland(&mut self) { + for _ in 0..5 { + let display_proc = vec![IBUS_DAEMON, GNOME_GOA_DAEMON, PLASMA_KDED5, RUSTDESK_TRAY]; + for proc in display_proc { + self.display = get_env("DISPLAY", &self.uid, proc); + self.xauth = get_env("XAUTHORITY", &self.uid, proc); + if !self.display.is_empty() && !self.xauth.is_empty() { + break; + } } + sleep_millis(300); } } fn get_display_x11(&mut self) { - let display_envs = vec![PLASMA_KDED5, GNOME_GOA_DAEMON, XFCE4_PANEL, SDDM_GREETER]; - for display_env in display_envs { - self.display = get_env_tries("DISPLAY", &self.uid, display_env, 10); - if !self.display.is_empty() { - break; + for _ in 0..10 { + let display_proc = vec![ + IBUS_DAEMON, + GNOME_GOA_DAEMON, + PLASMA_KDED5, + XFCE4_PANEL, + SDDM_GREETER, + ]; + for proc in display_proc { + self.display = get_env("DISPLAY", &self.uid, proc); + if !self.display.is_empty() { + break; + } } + sleep_millis(300); } if self.display.is_empty() { @@ -1032,12 +1025,21 @@ mod desktop { fn get_xauth_x11(&mut self) { // try by direct access to window manager process by name - let display_envs = vec![PLASMA_KDED5, GNOME_GOA_DAEMON, XFCE4_PANEL, SDDM_GREETER]; - for diplay_env in display_envs { - self.xauth = get_env_tries("XAUTHORITY", &self.uid, diplay_env, 10); - if !self.xauth.is_empty() { - break; + for _ in 0..10 { + let display_proc = vec![ + IBUS_DAEMON, + GNOME_GOA_DAEMON, + PLASMA_KDED5, + XFCE4_PANEL, + SDDM_GREETER, + ]; + for proc in display_proc { + self.xauth = get_env("XAUTHORITY", &self.uid, proc); + if !self.xauth.is_empty() { + break; + } } + sleep_millis(300); } // get from Xorg process, parameter and environment @@ -1124,6 +1126,11 @@ mod desktop { pub fn refresh(&mut self) { if !self.sid.is_empty() && is_active_and_seat0(&self.sid) { + // Wayland display and xauth may not be available in a short time after login. + if self.is_wayland() && !self.is_login_wayland() { + self.get_display_xauth_wayland(); + self.is_rustdesk_subprocess = false; + } return; } @@ -1146,8 +1153,7 @@ mod desktop { } if self.is_wayland() { - self.get_display_wayland(); - self.get_xauth_wayland(); + self.get_display_xauth_wayland(); self.is_rustdesk_subprocess = false; } else { self.get_display_x11(); From 4326bfa504c4f982088ef556da208b0a38fd87cb Mon Sep 17 00:00:00 2001 From: fufesou Date: Fri, 6 Oct 2023 20:51:29 -0500 Subject: [PATCH 3/4] fix, xwayland server envs, check Xwayland Signed-off-by: fufesou --- src/platform/linux.rs | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/src/platform/linux.rs b/src/platform/linux.rs index 3a140051c..e37e6f53c 100644 --- a/src/platform/linux.rs +++ b/src/platform/linux.rs @@ -900,12 +900,21 @@ pub fn change_resolution_directly(name: &str, width: usize, height: usize) -> Re Ok(()) } +#[inline] +pub fn is_xwayland_running() -> bool { + if let Ok(output) = run_cmds("pgrep -a Xwayland") { + return !output.contains("Xwayland"); + } + false +} + mod desktop { use super::*; pub const XFCE4_PANEL: &str = "xfce4-panel"; pub const SDDM_GREETER: &str = "sddm-greeter"; + const XWAYLAND: &str = "Xwayland"; const IBUS_DAEMON: &str = "ibus-daemon"; const PLASMA_KDED5: &str = "kded5"; const GNOME_GOA_DAEMON: &str = "goa-daemon"; @@ -938,9 +947,15 @@ mod desktop { self.sid.is_empty() || self.is_rustdesk_subprocess } - fn get_display_xauth_wayland(&mut self) { + fn get_display_xauth_xwayland(&mut self) { for _ in 0..5 { - let display_proc = vec![IBUS_DAEMON, GNOME_GOA_DAEMON, PLASMA_KDED5, RUSTDESK_TRAY]; + let display_proc = vec![ + XWAYLAND, + IBUS_DAEMON, + GNOME_GOA_DAEMON, + PLASMA_KDED5, + RUSTDESK_TRAY, + ]; for proc in display_proc { self.display = get_env("DISPLAY", &self.uid, proc); self.xauth = get_env("XAUTHORITY", &self.uid, proc); @@ -955,6 +970,7 @@ mod desktop { fn get_display_x11(&mut self) { for _ in 0..10 { let display_proc = vec![ + XWAYLAND, IBUS_DAEMON, GNOME_GOA_DAEMON, PLASMA_KDED5, @@ -1027,6 +1043,7 @@ mod desktop { // try by direct access to window manager process by name for _ in 0..10 { let display_proc = vec![ + XWAYLAND, IBUS_DAEMON, GNOME_GOA_DAEMON, PLASMA_KDED5, @@ -1127,8 +1144,8 @@ mod desktop { pub fn refresh(&mut self) { if !self.sid.is_empty() && is_active_and_seat0(&self.sid) { // Wayland display and xauth may not be available in a short time after login. - if self.is_wayland() && !self.is_login_wayland() { - self.get_display_xauth_wayland(); + if is_xwayland_running() && !self.is_login_wayland() { + self.get_display_xauth_xwayland(); self.is_rustdesk_subprocess = false; } return; @@ -1153,7 +1170,12 @@ mod desktop { } if self.is_wayland() { - self.get_display_xauth_wayland(); + if is_xwayland_running() { + self.get_display_xauth_xwayland(); + } else { + self.display = "".to_owned(); + self.xauth = "".to_owned(); + } self.is_rustdesk_subprocess = false; } else { self.get_display_x11(); From bd6323ccaee854da76951c989864d58af69e8475 Mon Sep 17 00:00:00 2001 From: fufesou Date: Fri, 6 Oct 2023 23:15:51 -0500 Subject: [PATCH 4/4] fix, xwayland server env, check xwayland running Signed-off-by: fufesou --- src/platform/linux.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/platform/linux.rs b/src/platform/linux.rs index e37e6f53c..0f926c469 100644 --- a/src/platform/linux.rs +++ b/src/platform/linux.rs @@ -903,7 +903,7 @@ pub fn change_resolution_directly(name: &str, width: usize, height: usize) -> Re #[inline] pub fn is_xwayland_running() -> bool { if let Ok(output) = run_cmds("pgrep -a Xwayland") { - return !output.contains("Xwayland"); + return output.contains("Xwayland"); } false } @@ -1143,7 +1143,7 @@ mod desktop { pub fn refresh(&mut self) { if !self.sid.is_empty() && is_active_and_seat0(&self.sid) { - // Wayland display and xauth may not be available in a short time after login. + // Xwayland display and xauth may not be available in a short time after login. if is_xwayland_running() && !self.is_login_wayland() { self.get_display_xauth_xwayland(); self.is_rustdesk_subprocess = false;