systemd_transient/
handle.rs1use crate::{
2 SystemdTransientManager, UnitExit,
3 dbus::unit::UnitProxy,
4 error::SystemdTransientError,
5 watch::{ExitWatch, WatchState},
6};
7
8#[derive(Debug)]
13pub struct TransientUnitHandle {
14 pub(crate) name: String,
15 pub(crate) manager: SystemdTransientManager,
16 pub(crate) unit: UnitProxy<'static>,
17 pub(crate) invocation_id: Vec<u8>,
18 pub(crate) watch: ExitWatch,
19 pub(crate) released: bool,
20}
21
22impl TransientUnitHandle {
23 pub async fn stop(&self) -> Result<UnitExit, SystemdTransientError> {
33 if let WatchState::Exited(exit) = self.watch.current() {
34 return Ok(exit);
35 }
36
37 if self.unit.invocation_id().await? != self.invocation_id {
38 return match self.watch.current() {
39 WatchState::Exited(exit) => Ok(exit),
40 _ => Err(SystemdTransientError::UnitRestarted {
41 name: self.name.clone(),
42 }),
43 };
44 }
45
46 self.manager.stop_job(&self.name).await?;
47
48 self.watch.wait().await
50 }
51
52 pub fn name(&self) -> &str {
53 &self.name
54 }
55
56 pub async fn wait_for_exit(&self) -> Result<UnitExit, SystemdTransientError> {
60 self.watch.wait().await
61 }
62
63 pub async fn release(mut self) -> Result<(), SystemdTransientError> {
66 self.released = true;
67 self.unit.unref().await?;
68 Ok(())
69 }
70}
71
72impl Drop for TransientUnitHandle {
73 fn drop(&mut self) {
76 if self.released {
77 return;
78 }
79 if let Ok(rt) = tokio::runtime::Handle::try_current() {
80 let unit = self.unit.clone();
81 rt.spawn(async move {
82 if let Err(err) = unit.unref().await {
83 tracing::warn!("releasing unit {} failed: {}", unit.inner().path(), err);
84 }
85 });
86 }
87 }
88}