refactor: restart notifications and panel when the other exits
This commit is contained in:
parent
ac889a2d57
commit
59ddbfcac0
2 changed files with 130 additions and 65 deletions
116
src/main.rs
116
src/main.rs
|
|
@ -8,7 +8,10 @@ mod process;
|
||||||
mod service;
|
mod service;
|
||||||
mod systemd;
|
mod systemd;
|
||||||
|
|
||||||
use std::os::fd::AsRawFd;
|
use std::{
|
||||||
|
os::fd::AsRawFd,
|
||||||
|
sync::{Arc, Mutex},
|
||||||
|
};
|
||||||
|
|
||||||
use async_signals::Signals;
|
use async_signals::Signals;
|
||||||
use color_eyre::{eyre::WrapErr, Result};
|
use color_eyre::{eyre::WrapErr, Result};
|
||||||
|
|
@ -24,6 +27,8 @@ use tracing::{metadata::LevelFilter, Instrument};
|
||||||
use tracing_subscriber::{fmt, prelude::*, EnvFilter};
|
use tracing_subscriber::{fmt, prelude::*, EnvFilter};
|
||||||
use zbus::ConnectionBuilder;
|
use zbus::ConnectionBuilder;
|
||||||
|
|
||||||
|
use crate::notifications::notifications_process;
|
||||||
|
|
||||||
#[tokio::main(flavor = "current_thread")]
|
#[tokio::main(flavor = "current_thread")]
|
||||||
async fn main() -> Result<()> {
|
async fn main() -> Result<()> {
|
||||||
color_eyre::install().wrap_err("failed to install color_eyre error handler")?;
|
color_eyre::install().wrap_err("failed to install color_eyre error handler")?;
|
||||||
|
|
@ -74,72 +79,63 @@ async fn main() -> Result<()> {
|
||||||
|
|
||||||
let (panel_notifications_fd, daemon_notifications_fd) =
|
let (panel_notifications_fd, daemon_notifications_fd) =
|
||||||
notifications::create_socket().expect("Failed to create notification socket");
|
notifications::create_socket().expect("Failed to create notification socket");
|
||||||
let mut panel_env_vars = env_vars.clone();
|
|
||||||
|
|
||||||
panel_env_vars.push((
|
|
||||||
PANEL_NOTIFICATIONS_FD.to_string(),
|
|
||||||
panel_notifications_fd.as_raw_fd().to_string(),
|
|
||||||
));
|
|
||||||
|
|
||||||
let span = info_span!(parent: None, "cosmic-panel");
|
|
||||||
let stdout_span = span.clone();
|
|
||||||
let stderr_span = span;
|
|
||||||
process_manager
|
|
||||||
.start(
|
|
||||||
Process::new()
|
|
||||||
.with_executable("cosmic-panel")
|
|
||||||
.with_fds(move || vec![panel_notifications_fd.as_raw_fd()])
|
|
||||||
.with_on_stdout(move |_, _, line| {
|
|
||||||
let stdout_span = stdout_span.clone();
|
|
||||||
async move {
|
|
||||||
info!("{}", line);
|
|
||||||
}
|
|
||||||
.instrument(stdout_span)
|
|
||||||
})
|
|
||||||
.with_on_stderr(move |_, _, line| {
|
|
||||||
let stderr_span = stderr_span.clone();
|
|
||||||
async move {
|
|
||||||
warn!("{}", line);
|
|
||||||
}
|
|
||||||
.instrument(stderr_span)
|
|
||||||
})
|
|
||||||
.with_env(panel_env_vars.clone()),
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
.expect("failed to start panel");
|
|
||||||
|
|
||||||
let mut daemon_env_vars = env_vars.clone();
|
let mut daemon_env_vars = env_vars.clone();
|
||||||
daemon_env_vars.push((
|
daemon_env_vars.push((
|
||||||
DAEMON_NOTIFICATIONS_FD.to_string(),
|
DAEMON_NOTIFICATIONS_FD.to_string(),
|
||||||
daemon_notifications_fd.as_raw_fd().to_string(),
|
daemon_notifications_fd.as_raw_fd().to_string(),
|
||||||
));
|
));
|
||||||
let span = info_span!(parent: None, "cosmic-notifications");
|
let mut panel_env_vars = env_vars.clone();
|
||||||
let stdout_span = span.clone();
|
panel_env_vars.push((
|
||||||
let stderr_span = span;
|
PANEL_NOTIFICATIONS_FD.to_string(),
|
||||||
|
panel_notifications_fd.as_raw_fd().to_string(),
|
||||||
|
));
|
||||||
|
|
||||||
process_manager
|
let panel_key = Arc::new(Mutex::new(None));
|
||||||
.start(
|
let notif_key = Arc::new(Mutex::new(None));
|
||||||
Process::new()
|
|
||||||
.with_executable("cosmic-notifications")
|
let notifications_span = info_span!(parent: None, "cosmic-notifications");
|
||||||
.with_fds(move || vec![daemon_notifications_fd.as_raw_fd()])
|
let panel_span = info_span!(parent: None, "cosmic-panel");
|
||||||
.with_on_stdout(move |_, _, line| {
|
|
||||||
let stdout_span = stdout_span.clone();
|
let mut guard = notif_key.lock().unwrap();
|
||||||
async move {
|
*guard = Some(
|
||||||
info!("{}", line);
|
process_manager
|
||||||
}
|
.start(notifications_process(
|
||||||
.instrument(stdout_span)
|
notifications_span.clone(),
|
||||||
})
|
"cosmic-notifications",
|
||||||
.with_on_stderr(move |_, _, line| {
|
notif_key.clone(),
|
||||||
let stderr_span = stderr_span.clone();
|
daemon_env_vars.clone(),
|
||||||
async move {
|
daemon_notifications_fd.as_raw_fd(),
|
||||||
warn!("{}", line);
|
panel_span.clone(),
|
||||||
}
|
"cosmic-panel",
|
||||||
.instrument(stderr_span)
|
panel_key.clone(),
|
||||||
})
|
panel_env_vars.clone(),
|
||||||
.with_env(daemon_env_vars.clone()),
|
panel_notifications_fd.as_raw_fd(),
|
||||||
)
|
))
|
||||||
.await
|
.await
|
||||||
.expect("failed to start notifications daemon");
|
.expect("failed to start notifications daemon"),
|
||||||
|
);
|
||||||
|
drop(guard);
|
||||||
|
|
||||||
|
let mut guard = panel_key.lock().unwrap();
|
||||||
|
*guard = Some(
|
||||||
|
process_manager
|
||||||
|
.start(notifications_process(
|
||||||
|
panel_span,
|
||||||
|
"cosmic-panel",
|
||||||
|
panel_key.clone(),
|
||||||
|
panel_env_vars,
|
||||||
|
panel_notifications_fd.as_raw_fd(),
|
||||||
|
notifications_span,
|
||||||
|
"cosmic-notifications",
|
||||||
|
notif_key,
|
||||||
|
daemon_env_vars,
|
||||||
|
daemon_notifications_fd.as_raw_fd(),
|
||||||
|
))
|
||||||
|
.await
|
||||||
|
.expect("failed to start panel"),
|
||||||
|
);
|
||||||
|
drop(guard);
|
||||||
|
|
||||||
let span = info_span!(parent: None, "cosmic-app-library");
|
let span = info_span!(parent: None, "cosmic-app-library");
|
||||||
start_component("cosmic-app-library", span, &process_manager, &env_vars).await;
|
start_component("cosmic-app-library", span, &process_manager, &env_vars).await;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,11 @@
|
||||||
use color_eyre::eyre::Context;
|
use color_eyre::eyre::Context;
|
||||||
use color_eyre::Result;
|
use color_eyre::Result;
|
||||||
use std::os::fd::OwnedFd;
|
use launch_pad::process::Process;
|
||||||
|
use launch_pad::ProcessKey;
|
||||||
|
use std::os::fd::{OwnedFd, RawFd};
|
||||||
use std::os::unix::net::UnixStream;
|
use std::os::unix::net::UnixStream;
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
use tracing::Instrument;
|
||||||
|
|
||||||
pub fn create_socket() -> Result<(OwnedFd, OwnedFd)> {
|
pub fn create_socket() -> Result<(OwnedFd, OwnedFd)> {
|
||||||
// Create a new pair of unnamed Unix sockets
|
// Create a new pair of unnamed Unix sockets
|
||||||
|
|
@ -10,12 +14,77 @@ pub fn create_socket() -> Result<(OwnedFd, OwnedFd)> {
|
||||||
// Turn the sockets into non-blocking fd, which we can pass to the child
|
// Turn the sockets into non-blocking fd, which we can pass to the child
|
||||||
// process
|
// process
|
||||||
sock_1
|
sock_1
|
||||||
.set_nonblocking(false)
|
.set_nonblocking(true)
|
||||||
.wrap_err("failed to mark client socket as blocking")?;
|
.wrap_err("failed to mark client socket as non-blocking")?;
|
||||||
|
|
||||||
sock_2
|
sock_2
|
||||||
.set_nonblocking(false)
|
.set_nonblocking(true)
|
||||||
.wrap_err("failed to mark client socket as blocking")?;
|
.wrap_err("failed to mark client socket as non-blocking")?;
|
||||||
|
|
||||||
Ok((OwnedFd::from(sock_1), OwnedFd::from(sock_2)))
|
Ok((OwnedFd::from(sock_1), OwnedFd::from(sock_2)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn notifications_process(
|
||||||
|
span: tracing::Span,
|
||||||
|
cmd: &'static str,
|
||||||
|
key: Arc<Mutex<Option<ProcessKey>>>,
|
||||||
|
env_vars: Vec<(String, String)>,
|
||||||
|
fd: RawFd,
|
||||||
|
restart_span: tracing::Span,
|
||||||
|
restart_cmd: &'static str,
|
||||||
|
restart_key: Arc<Mutex<Option<ProcessKey>>>,
|
||||||
|
restart_env_vars: Vec<(String, String)>,
|
||||||
|
restart_fd: RawFd,
|
||||||
|
) -> Process {
|
||||||
|
let stdout_span = span.clone();
|
||||||
|
let stderr_span = span.clone();
|
||||||
|
let env_clone = env_vars.clone();
|
||||||
|
Process::new()
|
||||||
|
.with_executable(cmd)
|
||||||
|
.with_fds(move || vec![fd])
|
||||||
|
.with_on_stdout(move |_, _, line| {
|
||||||
|
let stdout_span = stdout_span.clone();
|
||||||
|
async move {
|
||||||
|
info!("{}", line);
|
||||||
|
}
|
||||||
|
.instrument(stdout_span)
|
||||||
|
})
|
||||||
|
.with_on_stderr(move |_, _, line| {
|
||||||
|
let stderr_span = stderr_span.clone();
|
||||||
|
async move {
|
||||||
|
warn!("{}", line);
|
||||||
|
}
|
||||||
|
.instrument(stderr_span)
|
||||||
|
})
|
||||||
|
.with_on_exit(move |pman, _, _, will_restart| {
|
||||||
|
// force restart of notifications / panel when the other exits
|
||||||
|
let new_process = notifications_process(
|
||||||
|
restart_span.clone(),
|
||||||
|
restart_cmd,
|
||||||
|
restart_key.clone(),
|
||||||
|
restart_env_vars.clone(),
|
||||||
|
restart_fd,
|
||||||
|
span.clone(),
|
||||||
|
cmd,
|
||||||
|
key.clone(),
|
||||||
|
env_clone.clone(),
|
||||||
|
fd,
|
||||||
|
);
|
||||||
|
let restart_key = restart_key.clone();
|
||||||
|
async move {
|
||||||
|
if will_restart {
|
||||||
|
let Some(old) = restart_key.lock().unwrap().clone() else {
|
||||||
|
error!("Couldn't stop previous invocation of {}", cmd);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
_ = pman.stop_process(old).await;
|
||||||
|
|
||||||
|
if let Ok(new) = pman.start(new_process).await {
|
||||||
|
let mut guard = restart_key.lock().unwrap();
|
||||||
|
*guard = Some(new);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.with_env(env_vars)
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue