diff --git a/com.steampowered.SteamOSManager1.xml b/com.steampowered.SteamOSManager1.xml index e56459b..789f72d 100644 --- a/com.steampowered.SteamOSManager1.xml +++ b/com.steampowered.SteamOSManager1.xml @@ -104,13 +104,13 @@ UpdateBios: Perform a BIOS update. - - @objectpath: An object path that can be used to pause/resume/cancel/kill the operation + + @jobpath: An object path that can be used to pause/resume/cancel the operation Version available: 8 --> - + - + - + - + - + - - - - - + + + + - + - + diff --git a/src/bin/steamosctl.rs b/src/bin/steamosctl.rs index d2ca6ee..54461d8 100644 --- a/src/bin/steamosctl.rs +++ b/src/bin/steamosctl.rs @@ -233,7 +233,7 @@ async fn main() -> Result<()> { } Commands::SetWifiBackend { backend } => { proxy.set_wifi_backend(*backend as u32).await?; - }, + } Commands::GetWifiBackend => { let backend = proxy.wifi_backend().await?; match WifiBackend::try_from(backend) { diff --git a/src/process.rs b/src/process.rs index 4aabc12..6f182ba 100644 --- a/src/process.rs +++ b/src/process.rs @@ -19,7 +19,7 @@ use zbus::{fdo, interface}; use crate::error::to_zbus_fdo_error; -const PROCESS_PREFIX: &str = "/com/steampowered/SteamOSManager1/Process"; +const PROCESS_PREFIX: &str = "/com/steampowered/SteamOSManager1/Job"; pub struct ProcessManager { // The thing that manages subprocesses. @@ -29,7 +29,7 @@ pub struct ProcessManager { next_process: u32, } -pub struct SubProcess { +pub struct Job { process: Child, paused: bool, exit_code: Option, @@ -63,14 +63,11 @@ impl ProcessManager { zbus::zvariant::OwnedObjectPath::try_from(path).map_err(to_zbus_fdo_error) } - pub async fn run_long_command( - executable: &str, - args: &[impl AsRef], - ) -> Result { + pub async fn run_long_command(executable: &str, args: &[impl AsRef]) -> Result { // Run the given executable with the given arguments // Return an id that can be used later to pause/cancel/resume as needed let child = Command::new(executable).args(args).spawn()?; - Ok(SubProcess { + Ok(Job { process: child, paused: false, exit_code: None, @@ -78,7 +75,7 @@ impl ProcessManager { } } -impl SubProcess { +impl Job { fn send_signal(&self, signal: nix::sys::signal::Signal) -> Result<()> { let pid = match self.process.id() { Some(id) => id, @@ -114,7 +111,7 @@ impl SubProcess { Ok(self.exit_code) } - async fn exit_code_internal(&mut self) -> Result { + async fn wait_internal(&mut self) -> Result { if let Some(code) = self.exit_code { // Just give the exit_code if we have it already Ok(code) @@ -126,8 +123,8 @@ impl SubProcess { } } -#[interface(name = "com.steampowered.SteamOSManager1.SubProcess")] -impl SubProcess { +#[interface(name = "com.steampowered.SteamOSManager1.Job")] +impl Job { pub async fn pause(&mut self) -> fdo::Result<()> { if self.paused { return Err(fdo::Error::Failed("Already paused".to_string())); @@ -149,10 +146,13 @@ impl SubProcess { result } - pub async fn cancel(&mut self) -> fdo::Result<()> { + pub async fn cancel(&mut self, force: bool) -> fdo::Result<()> { if self.try_wait().map_err(to_zbus_fdo_error)?.is_none() { - self.send_signal(Signal::SIGTERM) - .map_err(to_zbus_fdo_error)?; + self.send_signal(match force { + true => Signal::SIGKILL, + false => Signal::SIGTERM, + }) + .map_err(to_zbus_fdo_error)?; if self.paused { self.resume().await?; } @@ -160,19 +160,12 @@ impl SubProcess { Ok(()) } - pub async fn kill(&mut self) -> fdo::Result<()> { - match self.try_wait().map_err(to_zbus_fdo_error)? { - Some(_) => Ok(()), - None => self.send_signal(signal::SIGKILL).map_err(to_zbus_fdo_error), - } - } - pub async fn wait(&mut self) -> fdo::Result { if self.paused { self.resume().await?; } - let code = match self.exit_code_internal().await.map_err(to_zbus_fdo_error) { + let code = match self.wait_internal().await.map_err(to_zbus_fdo_error) { Ok(v) => v, Err(_) => { return Err(fdo::Error::Failed("Unable to get exit code".to_string())); @@ -181,15 +174,6 @@ impl SubProcess { self.exit_code = Some(code); Ok(code) } - - pub async fn exit_code(&mut self) -> fdo::Result { - match self.try_wait() { - Ok(Some(i)) => Ok(i), - _ => Err(zbus::fdo::Error::Failed( - "Unable to get exit code. The process may still be running.".to_string(), - )), - } - } } #[cfg(not(test))] @@ -297,10 +281,10 @@ mod test { let mut sleep_process = ProcessManager::run_long_command("/usr/bin/sleep", &["0.1"]) .await .unwrap(); - sleep_process.kill().await.expect("kill"); + sleep_process.cancel(true).await.expect("kill"); // Killing a process should be idempotent - sleep_process.kill().await.expect("kill"); + sleep_process.cancel(true).await.expect("kill"); assert_eq!( sleep_process.wait().await.unwrap(), @@ -319,28 +303,13 @@ mod test { assert_eq!(pause_process.try_wait().expect("try_wait"), None); // Canceling a process should unpause it - pause_process.cancel().await.expect("pause"); + pause_process.cancel(false).await.expect("pause"); assert_eq!( pause_process.wait().await.unwrap(), -(Signal::SIGTERM as i32) ); } - #[tokio::test] - async fn test_exit_code_early() { - let _h = testing::start(); - - let mut sleep_process = ProcessManager::run_long_command("/usr/bin/sleep", &["0.1"]) - .await - .unwrap(); - assert_eq!( - sleep_process.exit_code().await.unwrap_err().to_string(), - "org.freedesktop.DBus.Error.Failed: Unable to get exit code. The process may still be running." - ); - - assert_eq!(sleep_process.wait().await.unwrap(), 0); - } - #[tokio::test] async fn test_run_script() { let h = testing::start(); diff --git a/src/proxy.rs b/src/proxy.rs index 69f962d..5e096bf 100644 --- a/src/proxy.rs +++ b/src/proxy.rs @@ -123,12 +123,12 @@ trait Manager { #[proxy( default_service = "com.steampowered.SteamOSManager1", - interface = "com.steampowered.SteamOSManager1.SubProcess", + interface = "com.steampowered.SteamOSManager1.Job", assume_defaults = true )] -trait SubProcess { +trait Job { /// Cancel method - fn cancel(&self) -> zbus::Result<()>; + fn cancel(&self, force: bool) -> zbus::Result<()>; /// ExitCode method fn exit_code(&self) -> zbus::Result; @@ -136,9 +136,6 @@ trait SubProcess { /// WaitForExitCode method fn wait_for_exit_code(&self) -> zbus::Result; - /// Kill method - fn kill(&self) -> zbus::Result<()>; - /// Pause method fn pause(&self) -> zbus::Result<()>;