make multiple daemons possible and make commands time out
This commit is contained in:
parent
9a8bbf4114
commit
5b3344fc5b
9 changed files with 91 additions and 30 deletions
17
Cargo.lock
generated
17
Cargo.lock
generated
|
@ -100,6 +100,12 @@ version = "1.0.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
|
||||
|
||||
[[package]]
|
||||
name = "beef"
|
||||
version = "0.4.4"
|
||||
|
@ -279,6 +285,7 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"anyhow",
|
||||
"async-stream",
|
||||
"base64",
|
||||
"bincode",
|
||||
"debug_stub_derive",
|
||||
"derive_more",
|
||||
|
@ -314,6 +321,7 @@ dependencies = [
|
|||
"tokio-stream",
|
||||
"tokio-util",
|
||||
"unescape",
|
||||
"wait-timeout",
|
||||
"x11rb",
|
||||
]
|
||||
|
||||
|
@ -1723,6 +1731,15 @@ version = "0.9.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
|
||||
|
||||
[[package]]
|
||||
name = "wait-timeout"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.9.0+wasi-snapshot-preview1"
|
||||
|
|
|
@ -58,6 +58,8 @@ tokio-util = "0.6"
|
|||
|
||||
nom = "6.1"
|
||||
dyn-clone = "1.0"
|
||||
base64 = "0.13"
|
||||
wait-timeout = "0.2"
|
||||
|
||||
[target.'cfg(target_os="linux")'.dependencies]
|
||||
inotify = "0.9"
|
||||
|
|
|
@ -64,6 +64,7 @@ impl ScriptVar {
|
|||
|
||||
/// Run a command and get the output
|
||||
fn run_command(cmd: &str) -> Result<PrimitiveValue> {
|
||||
log::debug!("Running command: {}", cmd);
|
||||
let output = String::from_utf8(Command::new("/bin/sh").arg("-c").arg(cmd).output()?.stdout)?;
|
||||
let output = output.trim_matches('\n');
|
||||
Ok(PrimitiveValue::from(output))
|
||||
|
|
|
@ -6,8 +6,9 @@ use tokio::{
|
|||
sync::mpsc::*,
|
||||
};
|
||||
|
||||
pub async fn run_server(evt_send: UnboundedSender<app::DaemonCommand>) -> Result<()> {
|
||||
let listener = tokio::net::UnixListener::bind(&*crate::IPC_SOCKET_PATH)?;
|
||||
pub async fn run_server<P: AsRef<std::path::Path>>(evt_send: UnboundedSender<app::DaemonCommand>, socket_path: P) -> Result<()> {
|
||||
let socket_path = socket_path.as_ref();
|
||||
let listener = { tokio::net::UnixListener::bind(socket_path)? };
|
||||
log::info!("IPC server initialized");
|
||||
crate::loop_select_exiting! {
|
||||
connection = listener.accept() => match connection {
|
||||
|
|
34
src/main.rs
34
src/main.rs
|
@ -31,7 +31,7 @@ pub mod value;
|
|||
pub mod widgets;
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
pub static ref IPC_SOCKET_PATH: std::path::PathBuf = std::env::var("XDG_RUNTIME_DIR")
|
||||
static ref IPC_SOCKET_PATH: std::path::PathBuf = std::env::var("XDG_RUNTIME_DIR")
|
||||
.map(std::path::PathBuf::from)
|
||||
.unwrap_or_else(|_| std::path::PathBuf::from("/tmp"))
|
||||
.join("eww-server");
|
||||
|
@ -47,6 +47,21 @@ lazy_static::lazy_static! {
|
|||
.join("eww.log");
|
||||
}
|
||||
|
||||
pub struct Paths {}
|
||||
|
||||
pub fn calculate_socket_path<P: AsRef<std::path::Path>>(config_file_path: P) -> std::path::PathBuf {
|
||||
let daemon_id = base64::encode(format!("{}", config_file_path.as_ref().display()));
|
||||
let socket_filename = format!(
|
||||
"{}_{}",
|
||||
&*crate::IPC_SOCKET_PATH
|
||||
.file_name()
|
||||
.and_then(|x| x.to_str())
|
||||
.expect("Invalid socket path"),
|
||||
daemon_id,
|
||||
);
|
||||
crate::IPC_SOCKET_PATH.with_file_name(socket_filename).to_path_buf()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let opts: opts::Opt = opts::Opt::from_env();
|
||||
|
||||
|
@ -61,15 +76,16 @@ fn main() {
|
|||
.init();
|
||||
|
||||
let result: Result<_> = try {
|
||||
let socket_path = calculate_socket_path(opts.config_path.clone().unwrap_or(CONFIG_DIR.join("eww.xml")));
|
||||
match opts.action {
|
||||
opts::Action::ClientOnly(action) => {
|
||||
client::handle_client_only_action(action)?;
|
||||
}
|
||||
opts::Action::WithServer(action) => {
|
||||
log::info!("Trying to find server process");
|
||||
match net::UnixStream::connect(&*IPC_SOCKET_PATH) {
|
||||
log::info!("Trying to find server process at socket {}", socket_path.display());
|
||||
match net::UnixStream::connect(&socket_path) {
|
||||
Ok(stream) => {
|
||||
log::info!("Connected to Eww server.");
|
||||
log::info!("Connected to Eww server ({}).", &socket_path.display());
|
||||
let response =
|
||||
client::do_server_call(stream, action).context("Error while forwarding command to server")?;
|
||||
if let Some(response) = response {
|
||||
|
@ -87,17 +103,17 @@ fn main() {
|
|||
}
|
||||
}
|
||||
|
||||
opts::Action::Daemon { config } => {
|
||||
opts::Action::Daemon => {
|
||||
// make sure that there isn't already a Eww daemon running.
|
||||
if check_server_running(&*IPC_SOCKET_PATH) {
|
||||
if check_server_running(&socket_path) {
|
||||
eprintln!("Eww server already running.");
|
||||
std::process::exit(1);
|
||||
} else {
|
||||
log::info!("Initializing Eww server.");
|
||||
let _ = std::fs::remove_file(&*crate::IPC_SOCKET_PATH);
|
||||
log::info!("Initializing Eww server. ({})", socket_path.display());
|
||||
let _ = std::fs::remove_file(socket_path);
|
||||
|
||||
println!("Run `eww logs` to see any errors, warnings or information while editing your configuration.");
|
||||
server::initialize_server(config)?;
|
||||
server::initialize_server(opts.config_path)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
23
src/opts.rs
23
src/opts.rs
|
@ -12,6 +12,7 @@ use crate::{
|
|||
#[derive(Debug, Serialize, Deserialize, PartialEq)]
|
||||
pub struct Opt {
|
||||
pub log_debug: bool,
|
||||
pub config_path: Option<std::path::PathBuf>,
|
||||
pub action: Action,
|
||||
}
|
||||
|
||||
|
@ -21,6 +22,10 @@ struct RawOpt {
|
|||
#[structopt(long = "debug", global = true)]
|
||||
log_debug: bool,
|
||||
|
||||
/// override config-file path (path to eww.xml)
|
||||
#[structopt(short, long, global = true)]
|
||||
config: Option<std::path::PathBuf>,
|
||||
|
||||
#[structopt(subcommand)]
|
||||
action: Action,
|
||||
}
|
||||
|
@ -29,11 +34,7 @@ struct RawOpt {
|
|||
pub enum Action {
|
||||
/// Start the Eww daemon.
|
||||
#[structopt(name = "daemon", alias = "d")]
|
||||
Daemon {
|
||||
/// Custom Config Path
|
||||
#[structopt(short, long)]
|
||||
config: Option<std::path::PathBuf>,
|
||||
},
|
||||
Daemon,
|
||||
|
||||
#[structopt(flatten)]
|
||||
ClientOnly(ActionClientOnly),
|
||||
|
@ -128,8 +129,16 @@ impl Opt {
|
|||
|
||||
impl From<RawOpt> for Opt {
|
||||
fn from(other: RawOpt) -> Self {
|
||||
let RawOpt { action, log_debug } = other;
|
||||
Opt { action, log_debug }
|
||||
let RawOpt {
|
||||
action,
|
||||
log_debug,
|
||||
config,
|
||||
} = other;
|
||||
Opt {
|
||||
action,
|
||||
log_debug,
|
||||
config_path: config,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -89,12 +89,14 @@ fn init_async_part(config_file_path: PathBuf, scss_file_path: PathBuf, ui_send:
|
|||
rt.block_on(async {
|
||||
let filewatch_join_handle = {
|
||||
let ui_send = ui_send.clone();
|
||||
let config_file_path = config_file_path.clone();
|
||||
tokio::spawn(async move { run_filewatch(config_file_path, scss_file_path, ui_send).await })
|
||||
};
|
||||
|
||||
let ipc_server_join_handle = {
|
||||
let ui_send = ui_send.clone();
|
||||
tokio::spawn(async move { ipc_server::run_server(ui_send).await })
|
||||
let socket_path = crate::calculate_socket_path(config_file_path);
|
||||
tokio::spawn(async move { ipc_server::run_server(ui_send, socket_path).await })
|
||||
};
|
||||
|
||||
let forward_exit_to_app_handle = {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{config::window_definition::WindowName, eww_state::*, print_result_err, value::AttrName};
|
||||
use crate::{config::window_definition::WindowName, eww_state::*, value::AttrName};
|
||||
use anyhow::*;
|
||||
use gtk::prelude::*;
|
||||
use itertools::Itertools;
|
||||
|
@ -13,14 +13,27 @@ const CMD_STRING_PLACEHODLER: &str = "{}";
|
|||
|
||||
/// Run a command that was provided as an attribute. This command may use a
|
||||
/// placeholder ('{}') which will be replaced by the value provided as [`arg`]
|
||||
pub(self) fn run_command<T: std::fmt::Display>(cmd: &str, arg: T) {
|
||||
let cmd = cmd.replace(CMD_STRING_PLACEHODLER, &format!("{}", arg));
|
||||
let command_result = Command::new("/bin/sh")
|
||||
.arg("-c")
|
||||
.arg(&cmd)
|
||||
.spawn()
|
||||
.and_then(|mut child| child.wait());
|
||||
print_result_err!(format!("executing command {}", &cmd), command_result);
|
||||
pub(self) fn run_command<T: 'static + std::fmt::Display + Send + Sync>(cmd: &str, arg: T) {
|
||||
use wait_timeout::ChildExt;
|
||||
let cmd = cmd.to_string();
|
||||
std::thread::spawn(move || {
|
||||
let cmd = cmd.replace(CMD_STRING_PLACEHODLER, &format!("{}", arg));
|
||||
log::debug!("Running command from widget: {}", cmd);
|
||||
let child = Command::new("/bin/sh").arg("-c").arg(&cmd).spawn();
|
||||
match child {
|
||||
Ok(mut child) => match child.wait_timeout(std::time::Duration::from_millis(200)) {
|
||||
// child timed out
|
||||
Ok(None) => {
|
||||
eprintln!("WARNING: command {} timed out", &cmd);
|
||||
let _ = child.kill();
|
||||
let _ = child.wait();
|
||||
}
|
||||
Err(err) => eprintln!("Failed to execute command {}: {}", cmd, err),
|
||||
Ok(Some(_)) => {}
|
||||
},
|
||||
Err(err) => eprintln!("Failed to launch child process: {}", err),
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
struct BuilderArgs<'a, 'b, 'c, 'd> {
|
||||
|
|
|
@ -258,8 +258,8 @@ fn build_gtk_color_chooser(bargs: &mut BuilderArgs) -> Result<gtk::ColorChooserW
|
|||
// @prop onchange - runs the code when the color was selected
|
||||
prop(onchange: as_string) {
|
||||
let old_id = on_change_handler_id.replace(Some(
|
||||
gtk_widget.connect_color_activated(move |_a, gtk_widget| {
|
||||
run_command(&onchange, gtk_widget);
|
||||
gtk_widget.connect_color_activated(move |_a, color| {
|
||||
run_command(&onchange, color.clone());
|
||||
})
|
||||
));
|
||||
old_id.map(|id| gtk_widget.disconnect(id));
|
||||
|
|
Loading…
Add table
Reference in a new issue