Make daemon startup explicit
This commit is contained in:
parent
84cce399d0
commit
018bfee24c
4 changed files with 47 additions and 66 deletions
|
|
@ -20,7 +20,7 @@ pub fn handle_client_only_action(action: ActionClientOnly) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn forward_command_to_server(mut stream: UnixStream, action: opts::ActionWithServer) -> Result<()> {
|
pub fn do_server_call(mut stream: UnixStream, action: opts::ActionWithServer) -> Result<Option<String>> {
|
||||||
log::info!("Forwarding options to server");
|
log::info!("Forwarding options to server");
|
||||||
stream
|
stream
|
||||||
.set_nonblocking(false)
|
.set_nonblocking(false)
|
||||||
|
|
@ -43,8 +43,6 @@ pub fn forward_command_to_server(mut stream: UnixStream, action: opts::ActionWit
|
||||||
stream
|
stream
|
||||||
.read_to_string(&mut buf)
|
.read_to_string(&mut buf)
|
||||||
.context("Error reading response from server")?;
|
.context("Error reading response from server")?;
|
||||||
if !buf.is_empty() {
|
|
||||||
println!("{}", buf);
|
Ok(if buf.is_empty() { None } else { Some(buf) })
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
45
src/main.rs
45
src/main.rs
|
|
@ -53,16 +53,31 @@ fn main() {
|
||||||
}
|
}
|
||||||
opts::Action::WithServer(action) => {
|
opts::Action::WithServer(action) => {
|
||||||
log::info!("Trying to find server process");
|
log::info!("Trying to find server process");
|
||||||
if let Some(stream) = try_connect(&*IPC_SOCKET_PATH) {
|
match net::UnixStream::connect(&*IPC_SOCKET_PATH) {
|
||||||
log::info!("Connected to eww server.");
|
Ok(stream) => {
|
||||||
client::forward_command_to_server(stream, action).context("Error while forwarding command to server")?;
|
log::info!("Connected to Eww server.");
|
||||||
} else if action.needs_server_running() {
|
let response =
|
||||||
println!("No eww server running");
|
client::do_server_call(stream, action).context("Error while forwarding command to server")?;
|
||||||
|
if let Some(response) = response {
|
||||||
|
println!("{}", response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
println!("Failed to connect to the eww daemon.");
|
||||||
|
println!("Make sure to start the eww daemon process by running `eww daemon` first.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
opts::Action::Daemon => {
|
||||||
|
// make sure that there isn't already a Eww daemon running.
|
||||||
|
if check_server_running(&*IPC_SOCKET_PATH) {
|
||||||
|
eprintln!("Eww server already running.");
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
} else {
|
} else {
|
||||||
log::info!("No server running, initializing server...");
|
log::info!("Initializing Eww server.");
|
||||||
let _ = std::fs::remove_file(&*crate::IPC_SOCKET_PATH);
|
let _ = std::fs::remove_file(&*crate::IPC_SOCKET_PATH);
|
||||||
server::initialize_server(opts.should_detach, action)?;
|
server::initialize_server()?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -70,16 +85,14 @@ fn main() {
|
||||||
|
|
||||||
if let Err(e) = result {
|
if let Err(e) = result {
|
||||||
eprintln!("{:?}", e);
|
eprintln!("{:?}", e);
|
||||||
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_connect(path: &std::path::PathBuf) -> Option<net::UnixStream> {
|
/// Check if a eww server is currently running by trying to send a ping message to it.
|
||||||
if path.exists() {
|
fn check_server_running(socket_path: &std::path::PathBuf) -> bool {
|
||||||
for _ in 0..5 {
|
let response = net::UnixStream::connect(socket_path)
|
||||||
if let Ok(stream) = net::UnixStream::connect(&*IPC_SOCKET_PATH) {
|
.ok()
|
||||||
return Some(stream);
|
.and_then(|stream| client::do_server_call(stream, opts::ActionWithServer::Ping).ok());
|
||||||
}
|
response.is_some()
|
||||||
}
|
|
||||||
}
|
|
||||||
return None;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
28
src/opts.rs
28
src/opts.rs
|
|
@ -11,7 +11,6 @@ use crate::{
|
||||||
#[derive(Debug, Serialize, Deserialize, PartialEq)]
|
#[derive(Debug, Serialize, Deserialize, PartialEq)]
|
||||||
pub struct Opt {
|
pub struct Opt {
|
||||||
pub action: Action,
|
pub action: Action,
|
||||||
pub should_detach: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Helper struct that will be normalized into instance of [Opt]
|
/// Helper struct that will be normalized into instance of [Opt]
|
||||||
|
|
@ -23,6 +22,10 @@ struct RawOpt {
|
||||||
|
|
||||||
#[derive(StructOpt, Debug, Serialize, Deserialize, PartialEq)]
|
#[derive(StructOpt, Debug, Serialize, Deserialize, PartialEq)]
|
||||||
pub enum Action {
|
pub enum Action {
|
||||||
|
/// Start the Eww daemon.
|
||||||
|
#[structopt(name = "daemon")]
|
||||||
|
Daemon,
|
||||||
|
|
||||||
#[structopt(flatten)]
|
#[structopt(flatten)]
|
||||||
ClientOnly(ActionClientOnly),
|
ClientOnly(ActionClientOnly),
|
||||||
|
|
||||||
|
|
@ -39,10 +42,6 @@ pub enum ActionClientOnly {
|
||||||
|
|
||||||
#[derive(StructOpt, Debug, Serialize, Deserialize, PartialEq)]
|
#[derive(StructOpt, Debug, Serialize, Deserialize, PartialEq)]
|
||||||
pub enum ActionWithServer {
|
pub enum ActionWithServer {
|
||||||
/// Start the eww daemon.
|
|
||||||
#[structopt(name = "daemon")]
|
|
||||||
Daemon,
|
|
||||||
|
|
||||||
/// Ping the eww server, checking if it is reachable.
|
/// Ping the eww server, checking if it is reachable.
|
||||||
#[structopt(name = "ping")]
|
#[structopt(name = "ping")]
|
||||||
Ping,
|
Ping,
|
||||||
|
|
@ -113,10 +112,7 @@ impl Opt {
|
||||||
impl From<RawOpt> for Opt {
|
impl From<RawOpt> for Opt {
|
||||||
fn from(other: RawOpt) -> Self {
|
fn from(other: RawOpt) -> Self {
|
||||||
let RawOpt { action } = other;
|
let RawOpt { action } = other;
|
||||||
Opt {
|
Opt { action }
|
||||||
should_detach: action == Action::WithServer(ActionWithServer::Daemon),
|
|
||||||
action,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -130,7 +126,11 @@ fn parse_var_update_arg(s: &str) -> Result<(VarName, PrimitiveValue)> {
|
||||||
impl ActionWithServer {
|
impl ActionWithServer {
|
||||||
pub fn into_eww_command(self) -> (app::EwwCommand, Option<tokio::sync::mpsc::UnboundedReceiver<String>>) {
|
pub fn into_eww_command(self) -> (app::EwwCommand, Option<tokio::sync::mpsc::UnboundedReceiver<String>>) {
|
||||||
let command = match self {
|
let command = match self {
|
||||||
ActionWithServer::Daemon | ActionWithServer::Ping => app::EwwCommand::NoOp,
|
ActionWithServer::Ping => {
|
||||||
|
let (send, recv) = tokio::sync::mpsc::unbounded_channel();
|
||||||
|
let _ = send.send("pong".to_owned());
|
||||||
|
return (app::EwwCommand::NoOp, Some(recv));
|
||||||
|
}
|
||||||
ActionWithServer::Update { mappings } => app::EwwCommand::UpdateVars(mappings.into_iter().collect()),
|
ActionWithServer::Update { mappings } => app::EwwCommand::UpdateVars(mappings.into_iter().collect()),
|
||||||
ActionWithServer::OpenMany { windows } => app::EwwCommand::OpenMany(windows),
|
ActionWithServer::OpenMany { windows } => app::EwwCommand::OpenMany(windows),
|
||||||
ActionWithServer::OpenWindow {
|
ActionWithServer::OpenWindow {
|
||||||
|
|
@ -158,12 +158,4 @@ impl ActionWithServer {
|
||||||
};
|
};
|
||||||
(command, None)
|
(command, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// returns true if this command requires a server to already be running
|
|
||||||
pub fn needs_server_running(&self) -> bool {
|
|
||||||
match self {
|
|
||||||
ActionWithServer::OpenWindow { .. } | ActionWithServer::Daemon => false,
|
|
||||||
_ => true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,10 +12,8 @@ use tokio::{
|
||||||
sync::mpsc::*,
|
sync::mpsc::*,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn initialize_server(should_detach: bool, action: opts::ActionWithServer) -> Result<()> {
|
pub fn initialize_server() -> Result<()> {
|
||||||
if should_detach {
|
do_detach()?;
|
||||||
do_detach()?;
|
|
||||||
}
|
|
||||||
|
|
||||||
simple_signal::set_handler(&[simple_signal::Signal::Int, simple_signal::Signal::Term], move |_| {
|
simple_signal::set_handler(&[simple_signal::Signal::Int, simple_signal::Signal::Term], move |_| {
|
||||||
println!("Shutting down eww daemon...");
|
println!("Shutting down eww daemon...");
|
||||||
|
|
@ -24,6 +22,7 @@ pub fn initialize_server(should_detach: bool, action: opts::ActionWithServer) ->
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
let (ui_send, mut ui_recv) = tokio::sync::mpsc::unbounded_channel();
|
||||||
|
|
||||||
let config_file_path = crate::CONFIG_DIR.join("eww.xml");
|
let config_file_path = crate::CONFIG_DIR.join("eww.xml");
|
||||||
let config_dir = config_file_path
|
let config_dir = config_file_path
|
||||||
|
|
@ -36,7 +35,6 @@ pub fn initialize_server(should_detach: bool, action: opts::ActionWithServer) ->
|
||||||
let eww_config = config::EwwConfig::read_from_file(&config_file_path)?;
|
let eww_config = config::EwwConfig::read_from_file(&config_file_path)?;
|
||||||
|
|
||||||
gtk::init()?;
|
gtk::init()?;
|
||||||
let (ui_send, mut ui_recv) = tokio::sync::mpsc::unbounded_channel();
|
|
||||||
|
|
||||||
log::info!("Initializing script var handler");
|
log::info!("Initializing script var handler");
|
||||||
let script_var_handler = script_var_handler::init(ui_send.clone());
|
let script_var_handler = script_var_handler::init(ui_send.clone());
|
||||||
|
|
@ -58,13 +56,8 @@ pub fn initialize_server(should_detach: bool, action: opts::ActionWithServer) ->
|
||||||
app.load_css(&eww_css)?;
|
app.load_css(&eww_css)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// run the command that eww was started with
|
|
||||||
log::info!("running command: {:?}", &action);
|
|
||||||
let (command, maybe_response_recv) = action.into_eww_command();
|
|
||||||
app.handle_command(command);
|
|
||||||
|
|
||||||
// initialize all the handlers and tasks running asyncronously
|
// initialize all the handlers and tasks running asyncronously
|
||||||
init_async_part(config_file_path, scss_file_path, maybe_response_recv, ui_send);
|
init_async_part(config_file_path, scss_file_path, ui_send);
|
||||||
|
|
||||||
glib::MainContext::default().spawn_local(async move {
|
glib::MainContext::default().spawn_local(async move {
|
||||||
while let Some(event) = ui_recv.recv().await {
|
while let Some(event) = ui_recv.recv().await {
|
||||||
|
|
@ -78,28 +71,13 @@ pub fn initialize_server(should_detach: bool, action: opts::ActionWithServer) ->
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init_async_part(
|
fn init_async_part(config_file_path: PathBuf, scss_file_path: PathBuf, ui_send: UnboundedSender<app::EwwCommand>) {
|
||||||
config_file_path: PathBuf,
|
|
||||||
scss_file_path: PathBuf,
|
|
||||||
maybe_response_recv: Option<UnboundedReceiver<String>>,
|
|
||||||
ui_send: UnboundedSender<app::EwwCommand>,
|
|
||||||
) {
|
|
||||||
std::thread::spawn(move || {
|
std::thread::spawn(move || {
|
||||||
let rt = tokio::runtime::Builder::new_multi_thread()
|
let rt = tokio::runtime::Builder::new_multi_thread()
|
||||||
.enable_all()
|
.enable_all()
|
||||||
.build()
|
.build()
|
||||||
.expect("Failed to initialize tokio runtime");
|
.expect("Failed to initialize tokio runtime");
|
||||||
rt.block_on(async {
|
rt.block_on(async {
|
||||||
// TODO This really does not belong here at all :<
|
|
||||||
// print out the response of this initial command, if there is any
|
|
||||||
tokio::spawn(async {
|
|
||||||
if let Some(mut response_recv) = maybe_response_recv {
|
|
||||||
if let Ok(Some(response)) = tokio::time::timeout(Duration::from_millis(100), response_recv.recv()).await {
|
|
||||||
println!("{}", response);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let filewatch_join_handle = {
|
let filewatch_join_handle = {
|
||||||
let ui_send = ui_send.clone();
|
let ui_send = ui_send.clone();
|
||||||
tokio::spawn(async move { run_filewatch(config_file_path, scss_file_path, ui_send).await })
|
tokio::spawn(async move { run_filewatch(config_file_path, scss_file_path, ui_send).await })
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue