use std::process::{Child, Command, Stdio};
pub(crate) enum InhibitGuard {
#[cfg(feature = "inhibit")]
#[allow(dead_code)] Dbus(zbus::zvariant::OwnedFd),
Subprocess(Child),
None,
}
impl InhibitGuard {
pub(crate) fn acquire() -> Self {
#[cfg(feature = "inhibit")]
if let Some(guard) = try_dbus_inhibit() {
return guard;
}
if let Some(guard) = try_subprocess_inhibit() {
return guard;
}
log::warn!(
target: "inhibit",
"could not inhibit system sleep; neither logind DBus nor systemd-inhibit available"
);
Self::None
}
}
impl Drop for InhibitGuard {
fn drop(&mut self) {
match self {
#[cfg(feature = "inhibit")]
Self::Dbus(_) => {
log::debug!(target: "inhibit", "releasing DBus inhibit lock");
}
Self::Subprocess(child) => {
log::debug!(target: "inhibit", "killing systemd-inhibit subprocess");
let _ = child.kill();
let _ = child.wait();
}
Self::None => {}
}
}
}
#[cfg(feature = "inhibit")]
fn try_dbus_inhibit() -> Option<InhibitGuard> {
use zbus::blocking::Connection;
use zbus::zvariant::OwnedFd;
let conn: Connection = match Connection::system() {
Ok(c) => c,
Err(e) => {
log::debug!(target: "inhibit", "DBus connection failed: {e}");
return None;
}
};
let reply = match conn.call_method(
Some("org.freedesktop.login1"),
"/org/freedesktop/login1",
Some("org.freedesktop.login1.Manager"),
"Inhibit",
&(
"idle:sleep:shutdown",
"plasmoid-updater",
"Installing updates",
"block",
),
) {
Ok(r) => r,
Err(e) => {
log::debug!(target: "inhibit", "logind Inhibit() call failed: {e}");
return None;
}
};
match reply.body().deserialize::<OwnedFd>() {
Ok(fd) => {
log::debug!(target: "inhibit", "acquired logind DBus inhibit lock");
Some(InhibitGuard::Dbus(fd))
}
Err(e) => {
log::debug!(target: "inhibit", "failed to deserialize inhibit fd: {e}");
None
}
}
}
fn try_subprocess_inhibit() -> Option<InhibitGuard> {
let child = Command::new("systemd-inhibit")
.args([
"--what=idle:sleep:shutdown",
"--who=plasmoid-updater",
"--why=Installing updates",
"cat",
])
.stdin(Stdio::piped())
.stdout(Stdio::null())
.stderr(Stdio::null())
.spawn();
match child {
Ok(child) => {
log::debug!(target: "inhibit", "acquired systemd-inhibit subprocess lock");
Some(InhibitGuard::Subprocess(child))
}
Err(e) => {
log::debug!(target: "inhibit", "systemd-inhibit spawn failed: {e}");
None
}
}
}