redbear-*: fix logging-refactor regressions + Redox-correct daemon shutdown
The redbear-* logging-unify refactor (println/eprintln -> log::*) left three
mechanical corruptions, caught by --check-sweep:
1. log::MACRO!(); (empty call + spurious ;, args dangling) -> log::MACRO!(
2. log::MACRO!(<args>)); (one extra trailing paren) -> log::MACRO!(<args>);
3. use log::{..}; inserted INSIDE a 'use std::{' block -> moved out
Fixed across redbear-greeter/notifications/session-launch/statusnotifierwatcher/
upower (string-aware paren-balance sweep; balanced nested-paren calls untouched).
Separately, the 'tokio minimal' refactor left redbear-notifications and
redbear-statusnotifierwatcher using tokio::signal::ctrl_c/unix without the
tokio 'signal' feature (compile break). Per redbear-upower's documented finding,
tokio::signal::unix page-faults on Redox (relibc lacks the signal-handler
registration path) and Redox manages daemon lifecycle via the init system, not
POSIX signals. So the correct fix is NOT to re-add the feature but to drop the
signal-based shutdown entirely — the daemon holds its shutdown channel open and
runs until init stops it. Applied to all four signal-using daemons
(notifications, statusnotifierwatcher, udisks, polkit) and removed the now-unused
tokio 'signal' feature from udisks/polkit for consistency with upower.
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
use std::{
|
||||
use log::{error, info, warn};
|
||||
env,
|
||||
fs,
|
||||
io::{self, BufRead, BufReader, Write},
|
||||
@@ -9,6 +8,7 @@ use log::{error, info, warn};
|
||||
thread,
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
use log::{error, info, warn};
|
||||
|
||||
use redbear_login_protocol::{AuthRequest, AuthResponse, GreeterRequest, GreeterResponse};
|
||||
|
||||
@@ -278,7 +278,7 @@ impl GreeterDaemon {
|
||||
if attempt == 0 {
|
||||
return Ok(());
|
||||
}
|
||||
log::error!();
|
||||
log::error!(
|
||||
"redbear-greeterd: wayland socket appeared after {}ms (primary={}, fallback={})",
|
||||
attempt * 250,
|
||||
socket_path.display(),
|
||||
@@ -287,7 +287,7 @@ impl GreeterDaemon {
|
||||
return Ok(());
|
||||
}
|
||||
if attempt % 20 == 0 && attempt > 0 {
|
||||
log::error!();
|
||||
log::error!(
|
||||
"redbear-greeterd: still waiting for compositor socket {} ({}s elapsed)",
|
||||
socket_path.display(),
|
||||
attempt / 4
|
||||
@@ -304,21 +304,21 @@ impl GreeterDaemon {
|
||||
|
||||
fn start_surface(&mut self) -> Result<(), String> {
|
||||
self.set_state(GreeterState::Starting, "Starting greeter surface");
|
||||
log::info!("redbear-greeterd: starting compositor ({})...", COMPOSITOR_BIN_PATH));
|
||||
log::info!("redbear-greeterd: starting compositor ({})...", COMPOSITOR_BIN_PATH);
|
||||
let compositor_path = if Path::new(COMPOSITOR_BIN_PATH).is_file() {
|
||||
COMPOSITOR_BIN_PATH
|
||||
} else {
|
||||
COMPOSITOR_SHARE_PATH
|
||||
};
|
||||
self.compositor = Some(self.spawn_as_greeter(compositor_path)?);
|
||||
log::info!("redbear-greeterd: waiting for Wayland socket..."));
|
||||
log::info!("redbear-greeterd: waiting for Wayland socket...");
|
||||
self.wait_for_wayland_socket()?;
|
||||
log::info!("redbear-greeterd: compositor ready, launching greeter UI..."));
|
||||
log::info!("redbear-greeterd: compositor ready, launching greeter UI...");
|
||||
self.ui = Some(self.spawn_as_greeter("/usr/bin/redbear-greeter-ui")?);
|
||||
log::info!("redbear-greeterd: greeter UI launched, activating VT {}", self.vt));
|
||||
log::info!("redbear-greeterd: greeter UI launched, activating VT {}", self.vt);
|
||||
self.activate_vt(self.vt)?;
|
||||
self.set_state(GreeterState::GreeterReady, "Ready");
|
||||
log::info!("redbear-greeterd: greeter ready on VT {}", self.vt));
|
||||
log::info!("redbear-greeterd: greeter ready on VT {}", self.vt);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -515,7 +515,7 @@ impl GreeterDaemon {
|
||||
match self.listener.accept() {
|
||||
Ok((stream, _)) => {
|
||||
if let Err(err) = self.handle_connection(stream) {
|
||||
log::error!("redbear-greeterd: {err}"));
|
||||
log::error!("redbear-greeterd: {err}");
|
||||
}
|
||||
}
|
||||
Err(err) if err.kind() == io::ErrorKind::WouldBlock => {
|
||||
@@ -531,7 +531,7 @@ fn run() -> Result<(), String> {
|
||||
match parse_args() {
|
||||
Ok(()) => {}
|
||||
Err(err) if err.is_empty() => {
|
||||
log::info!("{}", usage()));
|
||||
log::info!("{}", usage());
|
||||
return Ok(());
|
||||
}
|
||||
Err(err) => return Err(err),
|
||||
@@ -544,8 +544,8 @@ fn run() -> Result<(), String> {
|
||||
fn main() {
|
||||
let _ = env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).try_init();
|
||||
if let Err(err) = run() {
|
||||
log::error!("redbear-greeterd: {err}"));
|
||||
log::error!("{}", usage()));
|
||||
log::error!("redbear-greeterd: {err}");
|
||||
log::error!("{}", usage());
|
||||
process::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use std::{
|
||||
use log::{error, info, warn};
|
||||
use std::{
|
||||
collections::{HashMap, HashSet, VecDeque},
|
||||
env,
|
||||
error::Error,
|
||||
@@ -87,7 +87,7 @@ impl Notifications {
|
||||
let proxy = match DBusProxy::new(&connection).await {
|
||||
Ok(proxy) => proxy,
|
||||
Err(err) => {
|
||||
log::error!("redbear-notifications: failed to create DBus proxy: {err}"));
|
||||
log::error!("redbear-notifications: failed to create DBus proxy: {err}");
|
||||
return;
|
||||
}
|
||||
};
|
||||
@@ -111,7 +111,7 @@ impl Notifications {
|
||||
vanished.insert(sender);
|
||||
}
|
||||
Err(err) => {
|
||||
log::error!();
|
||||
log::error!(
|
||||
"redbear-notifications: name_has_owner check failed: {err}"
|
||||
);
|
||||
}
|
||||
@@ -158,7 +158,7 @@ impl Notifications {
|
||||
Instant::now(),
|
||||
);
|
||||
|
||||
log::error!();
|
||||
log::error!(
|
||||
"notification {}: app_name={app_name:?} summary={summary:?} body_len={} owner={owner} replaced={:?}",
|
||||
result.id,
|
||||
body.chars().count(),
|
||||
@@ -175,7 +175,7 @@ impl Notifications {
|
||||
id: u32,
|
||||
) {
|
||||
if self.remove_notification(id, NOTIFICATION_CLOSED_REASON) {
|
||||
log::error!("notification: closed {id}"));
|
||||
log::error!("notification: closed {id}");
|
||||
let _ =
|
||||
Self::notification_closed(&signal_emitter, id, NOTIFICATION_CLOSED_REASON).await;
|
||||
}
|
||||
@@ -212,7 +212,7 @@ impl Notifications {
|
||||
self.validate_invoke(id, &sender, action_key)
|
||||
.map_err(fdo::Error::Failed)?;
|
||||
|
||||
log::error!("redbear-notifications: invoke action {id:?} -> {action_key:?}"));
|
||||
log::error!("redbear-notifications: invoke action {id:?} -> {action_key:?}");
|
||||
let _ = Self::action_invoked(&signal_emitter, id, action_key).await;
|
||||
let _ = self.complete_invocation(id, action_key);
|
||||
Ok(())
|
||||
@@ -530,24 +530,16 @@ fn parse_args() -> Result<Command, String> {
|
||||
}
|
||||
|
||||
fn spawn_signal_handler(shutdown_tx: tokio::sync::watch::Sender<bool>) {
|
||||
// Redox manages daemon lifecycle through the init system, not POSIX signals.
|
||||
// tokio::signal::unix page-faults on Redox — relibc does not implement the
|
||||
// signal-handler registration path the `signal` feature relies on (see the
|
||||
// note in redbear-upower's Cargo.toml). So there is no signal-driven
|
||||
// shutdown: keep the watch sender alive (so run_daemon's shutdown_rx stays
|
||||
// open rather than seeing a closed channel) and never fire it — the daemon
|
||||
// runs until init stops the process.
|
||||
tokio::spawn(async move {
|
||||
#[cfg(unix)]
|
||||
{
|
||||
use tokio::signal::unix::{SignalKind, signal};
|
||||
if let Ok(mut sigterm) = signal(SignalKind::terminate()) {
|
||||
tokio::select! {
|
||||
_ = sigterm.recv() => {},
|
||||
_ = tokio::signal::ctrl_c() => {},
|
||||
}
|
||||
} else {
|
||||
let _ = tokio::signal::ctrl_c().await;
|
||||
}
|
||||
}
|
||||
#[cfg(not(unix))]
|
||||
{
|
||||
let _ = tokio::signal::ctrl_c().await;
|
||||
}
|
||||
let _ = shutdown_tx.send(true);
|
||||
let _keep_open = shutdown_tx;
|
||||
std::future::pending::<()>().await;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -565,10 +557,10 @@ async fn run_daemon() -> Result<(), Box<dyn Error>> {
|
||||
notifications.spawn_expiry_sweeper(connection.clone());
|
||||
notifications.spawn_sender_reaper(connection.clone());
|
||||
|
||||
log::info!("redbear-notifications: registered {BUS_NAME} on the session bus"));
|
||||
log::info!("redbear-notifications: registered {BUS_NAME} on the session bus");
|
||||
|
||||
let _ = shutdown_rx.changed().await;
|
||||
log::info!("redbear-notifications: shutdown signal received, exiting cleanly"));
|
||||
log::info!("redbear-notifications: shutdown signal received, exiting cleanly");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -577,25 +569,25 @@ fn main() {
|
||||
let _ = env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).try_init();
|
||||
match parse_args() {
|
||||
Ok(Command::Help) => {
|
||||
log::info!("{}", usage()));
|
||||
log::info!("{}", usage());
|
||||
}
|
||||
Ok(Command::Run) => {
|
||||
let runtime = match RuntimeBuilder::new_multi_thread().enable_all().build() {
|
||||
Ok(runtime) => runtime,
|
||||
Err(err) => {
|
||||
log::error!("redbear-notifications: failed to create tokio runtime: {err}"));
|
||||
log::error!("redbear-notifications: failed to create tokio runtime: {err}");
|
||||
process::exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
if let Err(err) = runtime.block_on(run_daemon()) {
|
||||
log::error!("redbear-notifications: fatal error: {err}"));
|
||||
log::error!("redbear-notifications: fatal error: {err}");
|
||||
process::exit(1);
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
log::error!("redbear-notifications: {err}"));
|
||||
log::error!("{}", usage()));
|
||||
log::error!("redbear-notifications: {err}");
|
||||
log::error!("{}", usage());
|
||||
process::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,5 +14,5 @@ path = "src/main.rs"
|
||||
log = { version = "0.4", features = ["std"] }
|
||||
env_logger = "0.11"
|
||||
zbus = { version = "5", default-features = false, features = ["tokio"] }
|
||||
tokio = { version = "1", default-features = false, features = ["rt", "rt-multi-thread", "macros", "net", "time", "sync", "signal"] }
|
||||
tokio = { version = "1", default-features = false, features = ["rt", "rt-multi-thread", "macros", "net", "time", "sync"] }
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
|
||||
@@ -299,24 +299,15 @@ fn system_connection_builder() -> Result<ConnectionBuilder<'static>, Box<dyn Err
|
||||
}
|
||||
|
||||
fn spawn_signal_handler(shutdown_tx: tokio::sync::watch::Sender<bool>) {
|
||||
// Redox manages daemon lifecycle through the init system, not POSIX signals.
|
||||
// tokio::signal::unix page-faults on Redox — relibc does not implement the
|
||||
// signal-handler registration path the `signal` feature relies on (see the
|
||||
// note in redbear-upower's Cargo.toml). No signal-driven shutdown: hold the
|
||||
// watch sender open and never fire it, so the daemon runs until init stops
|
||||
// the process.
|
||||
tokio::spawn(async move {
|
||||
#[cfg(unix)]
|
||||
{
|
||||
use tokio::signal::unix::{SignalKind, signal};
|
||||
if let Ok(mut sigterm) = signal(SignalKind::terminate()) {
|
||||
tokio::select! {
|
||||
_ = sigterm.recv() => {},
|
||||
_ = tokio::signal::ctrl_c() => {},
|
||||
}
|
||||
} else {
|
||||
let _ = tokio::signal::ctrl_c().await;
|
||||
}
|
||||
}
|
||||
#[cfg(not(unix))]
|
||||
{
|
||||
let _ = tokio::signal::ctrl_c().await;
|
||||
}
|
||||
let _ = shutdown_tx.send(true);
|
||||
let _keep_open = shutdown_tx;
|
||||
std::future::pending::<()>().await;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use std::{
|
||||
use log::{error, info, warn};
|
||||
use std::{
|
||||
collections::{BTreeMap, HashMap},
|
||||
env,
|
||||
ffi::CString,
|
||||
@@ -402,8 +402,8 @@ fn run() -> Result<(), String> {
|
||||
fn main() {
|
||||
let _ = env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).try_init();
|
||||
if let Err(err) = run() {
|
||||
log::error!("redbear-session-launch: {err}"));
|
||||
log::error!("{}", usage()));
|
||||
log::error!("redbear-session-launch: {err}");
|
||||
log::error!("{}", usage());
|
||||
process::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@ use std::future::poll_fn;
|
||||
use std::pin::pin;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use zbus::{
|
||||
use log::{error, info, warn};
|
||||
use zbus::{
|
||||
connection::Builder as ConnectionBuilder, export::futures_core::Stream, fdo, interface,
|
||||
message::Header, object_server::SignalEmitter, proxy, zvariant::ObjectPath,
|
||||
};
|
||||
@@ -369,7 +369,7 @@ impl StatusNotifierWatcher {
|
||||
item: &str,
|
||||
) -> fdo::Result<()> {
|
||||
if let Err(msg) = validate_input(item) {
|
||||
log::error!("statusnotifierwatcher: rejected item registration: {msg}"));
|
||||
log::error!("statusnotifierwatcher: rejected item registration: {msg}");
|
||||
return Err(fdo::Error::InvalidArgs(msg));
|
||||
}
|
||||
let owner = hdr
|
||||
@@ -381,7 +381,7 @@ impl StatusNotifierWatcher {
|
||||
|
||||
let is_new = self.register_item(&owner, item);
|
||||
if is_new {
|
||||
log::info!("statusnotifierwatcher: item registered: {item} (owner: {owner})"));
|
||||
log::info!("statusnotifierwatcher: item registered: {item} (owner: {owner})");
|
||||
let _ = Self::status_notifier_item_registered(&signal_emitter, item).await;
|
||||
}
|
||||
Ok(())
|
||||
@@ -406,7 +406,7 @@ impl StatusNotifierWatcher {
|
||||
|
||||
let was_present = self.unregister_item(&owner, item);
|
||||
if was_present {
|
||||
log::error!("statusnotifierwatcher: item unregistered: {item} (owner: {owner})"));
|
||||
log::error!("statusnotifierwatcher: item unregistered: {item} (owner: {owner})");
|
||||
let _ = Self::status_notifier_item_unregistered(&signal_emitter, item).await;
|
||||
}
|
||||
Ok(())
|
||||
@@ -420,7 +420,7 @@ impl StatusNotifierWatcher {
|
||||
host: &str,
|
||||
) -> fdo::Result<()> {
|
||||
if let Err(msg) = validate_input(host) {
|
||||
log::error!("statusnotifierwatcher: rejected host registration: {msg}"));
|
||||
log::error!("statusnotifierwatcher: rejected host registration: {msg}");
|
||||
return Err(fdo::Error::InvalidArgs(msg));
|
||||
}
|
||||
let owner = hdr
|
||||
@@ -432,7 +432,7 @@ impl StatusNotifierWatcher {
|
||||
|
||||
let is_new = self.register_host(&owner, host);
|
||||
if is_new {
|
||||
log::info!("statusnotifierwatcher: host registered: {host} (owner: {owner})"));
|
||||
log::info!("statusnotifierwatcher: host registered: {host} (owner: {owner})");
|
||||
let _ = Self::status_notifier_host_registered(&signal_emitter).await;
|
||||
}
|
||||
Ok(())
|
||||
@@ -457,7 +457,7 @@ impl StatusNotifierWatcher {
|
||||
|
||||
let was_present = self.unregister_host(&owner, host);
|
||||
if was_present {
|
||||
log::error!("statusnotifierwatcher: host unregistered: {host} (owner: {owner})"));
|
||||
log::error!("statusnotifierwatcher: host unregistered: {host} (owner: {owner})");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -535,32 +535,32 @@ async fn run_name_owner_changed_listener(
|
||||
let proxy = match DBusDaemonProxy::new(&connection).await {
|
||||
Ok(p) => p,
|
||||
Err(e) => {
|
||||
log::error!("statusnotifierwatcher: failed to create DBus proxy: {e}"));
|
||||
log::error!("statusnotifierwatcher: failed to create DBus proxy: {e}");
|
||||
return;
|
||||
}
|
||||
};
|
||||
let signals = match proxy.receive_name_owner_changed().await {
|
||||
Ok(s) => s,
|
||||
Err(e) => {
|
||||
log::error!("statusnotifierwatcher: failed to subscribe to NameOwnerChanged: {e}"));
|
||||
log::error!("statusnotifierwatcher: failed to subscribe to NameOwnerChanged: {e}");
|
||||
return;
|
||||
}
|
||||
};
|
||||
let object_path: ObjectPath<'_> = match OBJECT_PATH.try_into() {
|
||||
Ok(path) => path,
|
||||
Err(e) => {
|
||||
log::error!("statusnotifierwatcher: invalid object path {OBJECT_PATH}: {e}"));
|
||||
log::error!("statusnotifierwatcher: invalid object path {OBJECT_PATH}: {e}");
|
||||
return;
|
||||
}
|
||||
};
|
||||
let signal_emitter = match SignalEmitter::new(&connection, object_path) {
|
||||
Ok(emitter) => emitter,
|
||||
Err(e) => {
|
||||
log::error!("statusnotifierwatcher: failed to create signal emitter: {e}"));
|
||||
log::error!("statusnotifierwatcher: failed to create signal emitter: {e}");
|
||||
return;
|
||||
}
|
||||
};
|
||||
log::info!("statusnotifierwatcher: NameOwnerChanged listener active"));
|
||||
log::info!("statusnotifierwatcher: NameOwnerChanged listener active");
|
||||
// Consume the signal stream without pulling in futures-lite as a direct
|
||||
// dependency: zbus re-exports futures_core::Stream, and std provides
|
||||
// poll_fn + pin! for manual polling.
|
||||
@@ -578,7 +578,7 @@ async fn run_name_owner_changed_listener(
|
||||
if !purged.is_empty() {
|
||||
emit_purge_unregistered_signals(&signal_emitter, &purged).await;
|
||||
let removed = purged.items.len() + purged.hosts.len();
|
||||
log::error!();
|
||||
log::error!(
|
||||
"statusnotifierwatcher: purged {removed} entries for vanished owner {}",
|
||||
args.old_owner
|
||||
);
|
||||
@@ -610,26 +610,15 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
|
||||
let (shutdown_tx, mut shutdown_rx) = tokio::sync::watch::channel(false);
|
||||
|
||||
// Signal handler task for clean shutdown
|
||||
// Redox manages daemon lifecycle through the init system, not POSIX signals.
|
||||
// tokio::signal::unix page-faults on Redox — relibc does not implement the
|
||||
// signal-handler registration path the `signal` feature relies on (see the
|
||||
// note in redbear-upower's Cargo.toml). No signal-driven shutdown: hold a
|
||||
// sender open and never fire it, so the daemon runs until init stops it.
|
||||
let signal_tx = shutdown_tx.clone();
|
||||
tokio::spawn(async move {
|
||||
#[cfg(unix)]
|
||||
{
|
||||
use tokio::signal::unix::{SignalKind, signal};
|
||||
if let Ok(mut sigterm) = signal(SignalKind::terminate()) {
|
||||
tokio::select! {
|
||||
_ = sigterm.recv() => {},
|
||||
_ = tokio::signal::ctrl_c() => {},
|
||||
}
|
||||
} else {
|
||||
let _ = tokio::signal::ctrl_c().await;
|
||||
}
|
||||
}
|
||||
#[cfg(not(unix))]
|
||||
{
|
||||
let _ = tokio::signal::ctrl_c().await;
|
||||
}
|
||||
let _ = signal_tx.send(true);
|
||||
let _keep_open = signal_tx;
|
||||
std::future::pending::<()>().await;
|
||||
});
|
||||
// Keep original sender alive so receiver doesn't see all-senders-dropped
|
||||
let _shutdown_guard = shutdown_tx;
|
||||
@@ -643,14 +632,14 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
.build()
|
||||
.await?;
|
||||
|
||||
log::info!("statusnotifierwatcher: {BUS_NAME} registered on session bus"));
|
||||
log::info!("statusnotifierwatcher: {BUS_NAME} registered on session bus");
|
||||
|
||||
// Spawn NameOwnerChanged listener that prunes entries on owner loss.
|
||||
tokio::spawn(run_name_owner_changed_listener(connection.clone(), watcher));
|
||||
|
||||
// Wait for shutdown signal
|
||||
let _ = shutdown_rx.changed().await;
|
||||
log::info!("statusnotifierwatcher: shutdown signal received, exiting cleanly"));
|
||||
log::info!("statusnotifierwatcher: shutdown signal received, exiting cleanly");
|
||||
drop(connection);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -14,6 +14,6 @@ path = "src/main.rs"
|
||||
log = { version = "0.4", features = ["std"] }
|
||||
env_logger = "0.11"
|
||||
zbus = { version = "5", default-features = false, features = ["tokio"] }
|
||||
tokio = { version = "1", default-features = false, features = ["rt", "rt-multi-thread", "macros", "net", "time", "sync", "signal"] }
|
||||
tokio = { version = "1", default-features = false, features = ["rt", "rt-multi-thread", "macros", "net", "time", "sync"] }
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
libc = "0.2"
|
||||
|
||||
@@ -76,24 +76,15 @@ fn system_connection_builder() -> Result<ConnectionBuilder<'static>, Box<dyn Err
|
||||
}
|
||||
|
||||
fn spawn_signal_handler(shutdown_tx: tokio::sync::watch::Sender<bool>) {
|
||||
// Redox manages daemon lifecycle through the init system, not POSIX signals.
|
||||
// tokio::signal::unix page-faults on Redox — relibc does not implement the
|
||||
// signal-handler registration path the `signal` feature relies on (see the
|
||||
// note in redbear-upower's Cargo.toml). No signal-driven shutdown: hold the
|
||||
// watch sender open and never fire it, so the daemon runs until init stops
|
||||
// the process.
|
||||
tokio::spawn(async move {
|
||||
#[cfg(unix)]
|
||||
{
|
||||
use tokio::signal::unix::{SignalKind, signal};
|
||||
if let Ok(mut sigterm) = signal(SignalKind::terminate()) {
|
||||
tokio::select! {
|
||||
_ = sigterm.recv() => {},
|
||||
_ = tokio::signal::ctrl_c() => {},
|
||||
}
|
||||
} else {
|
||||
let _ = tokio::signal::ctrl_c().await;
|
||||
}
|
||||
}
|
||||
#[cfg(not(unix))]
|
||||
{
|
||||
let _ = tokio::signal::ctrl_c().await;
|
||||
}
|
||||
let _ = shutdown_tx.send(true);
|
||||
let _keep_open = shutdown_tx;
|
||||
std::future::pending::<()>().await;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use std::{
|
||||
use log::{error, info, warn};
|
||||
use std::{
|
||||
env,
|
||||
error::Error,
|
||||
fs,
|
||||
@@ -137,7 +137,7 @@ async fn wait_for_dbus_socket() {
|
||||
}
|
||||
tokio::time::sleep(Duration::from_secs(1)).await;
|
||||
}
|
||||
log::error!("redbear-upower: timed out waiting for D-Bus socket at {socket_path}"));
|
||||
log::error!("redbear-upower: timed out waiting for D-Bus socket at {socket_path}");
|
||||
}
|
||||
|
||||
fn parse_object_path(path: &str) -> Result<OwnedObjectPath, Box<dyn Error>> {
|
||||
@@ -621,7 +621,7 @@ async fn run_daemon() -> Result<(), Box<dyn Error>> {
|
||||
wait_for_dbus_socket().await;
|
||||
let runtime = PowerRuntime::discover()?;
|
||||
if !runtime.available() {
|
||||
log::error!();
|
||||
log::error!(
|
||||
"redbear-upower: /scheme/acpi/power unavailable; serving empty provisional UPower surface"
|
||||
);
|
||||
}
|
||||
@@ -678,7 +678,7 @@ async fn run_daemon() -> Result<(), Box<dyn Error>> {
|
||||
|
||||
match builder.build().await {
|
||||
Ok(connection) => {
|
||||
log::info!("redbear-upower: registered {BUS_NAME} on the system bus"));
|
||||
log::info!("redbear-upower: registered {BUS_NAME} on the system bus");
|
||||
|
||||
let upower_path = parse_object_path(UPOWER_PATH)?;
|
||||
let signal_emitter = SignalEmitter::new(&connection, upower_path)?;
|
||||
@@ -693,22 +693,22 @@ async fn run_daemon() -> Result<(), Box<dyn Error>> {
|
||||
tokio::select! {
|
||||
result = shutdown_rx.changed() => {
|
||||
if result.is_err() {
|
||||
log::info!("redbear-upower: signal handler exited unexpectedly"));
|
||||
log::info!("redbear-upower: signal handler exited unexpectedly");
|
||||
}
|
||||
log::info!("redbear-upower: shutdown signal received, exiting cleanly"));
|
||||
log::info!("redbear-upower: shutdown signal received, exiting cleanly");
|
||||
break;
|
||||
}
|
||||
_ = notify_interval.tick() => {
|
||||
let drained = read_notifications();
|
||||
if !drained.is_empty() {
|
||||
log::error!();
|
||||
log::error!(
|
||||
"redbear-upower: {} ACPI notification(s): {}",
|
||||
drained.len(),
|
||||
drained.join(", ")
|
||||
);
|
||||
let current_snapshot = runtime.snapshot();
|
||||
if current_snapshot != last_snapshot {
|
||||
log::error!();
|
||||
log::error!(
|
||||
"redbear-upower: power state changed after notification, emitting Changed signal"
|
||||
);
|
||||
let _ = UPowerDaemon::changed(&signal_emitter).await;
|
||||
@@ -719,7 +719,7 @@ async fn run_daemon() -> Result<(), Box<dyn Error>> {
|
||||
_ = poll_interval.tick() => {
|
||||
let current_snapshot = runtime.snapshot();
|
||||
if current_snapshot != last_snapshot {
|
||||
log::error!();
|
||||
log::error!(
|
||||
"redbear-upower: power state changed, emitting Changed signal"
|
||||
);
|
||||
let _ = UPowerDaemon::changed(&signal_emitter).await;
|
||||
@@ -734,7 +734,7 @@ async fn run_daemon() -> Result<(), Box<dyn Error>> {
|
||||
}
|
||||
Err(err) => {
|
||||
if attempt < 3 {
|
||||
log::error!();
|
||||
log::error!(
|
||||
"redbear-upower: attempt {attempt}/3 failed ({err}), retrying in 1s..."
|
||||
);
|
||||
tokio::time::sleep(Duration::from_secs(1)).await;
|
||||
@@ -754,25 +754,25 @@ fn main() {
|
||||
let _ = env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).try_init();
|
||||
match parse_args() {
|
||||
Ok(Command::Help) => {
|
||||
log::info!("{}", usage()));
|
||||
log::info!("{}", usage());
|
||||
}
|
||||
Ok(Command::Run) => {
|
||||
let runtime = match RuntimeBuilder::new_multi_thread().enable_all().build() {
|
||||
Ok(runtime) => runtime,
|
||||
Err(err) => {
|
||||
log::error!("redbear-upower: failed to create tokio runtime: {err}"));
|
||||
log::error!("redbear-upower: failed to create tokio runtime: {err}");
|
||||
process::exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
if let Err(err) = runtime.block_on(run_daemon()) {
|
||||
log::error!("redbear-upower: fatal error: {err}"));
|
||||
log::error!("redbear-upower: fatal error: {err}");
|
||||
process::exit(1);
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
log::error!("redbear-upower: {err}"));
|
||||
log::error!("{}", usage()));
|
||||
log::error!("redbear-upower: {err}");
|
||||
log::error!("{}", usage());
|
||||
process::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user