summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKunal Mohan <kunalmohan99@gmail.com>2021-05-11 11:47:08 +0530
committerKunal Mohan <kunalmohan99@gmail.com>2021-05-15 22:14:34 +0530
commit0d792e26f23ad8e1fc2dd44555cae79427361c15 (patch)
tree7f2d28387b18dc089c961f7bffc60585f878df39
parent20d4b1826d89d8f547d57e19d6409a7fb114e05a (diff)
Switch to multiprocess model: Not looking good
-rw-r--r--Cargo.lock17
-rw-r--r--Cargo.toml1
-rw-r--r--src/cli.rs3
-rw-r--r--src/client/mod.rs34
-rw-r--r--src/common/os_input_output.rs26
-rw-r--r--src/main.rs22
-rw-r--r--src/server/mod.rs95
-rw-r--r--src/tests/fakes.rs2
8 files changed, 114 insertions, 86 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 2aeaa9269..92b2d0ca7 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -249,6 +249,12 @@ dependencies = [
]
[[package]]
+name = "boxfnonce"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5988cb1d626264ac94100be357308f29ff7cbdd3b36bda27f450a4ee3f713426"
+
+[[package]]
name = "bumpalo"
version = "3.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -468,6 +474,16 @@ dependencies = [
]
[[package]]
+name = "daemonize"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "70c24513e34f53b640819f0ac9f705b673fcf4006d7aab8778bee72ebfc89815"
+dependencies = [
+ "boxfnonce",
+ "libc",
+]
+
+[[package]]
name = "darling"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2261,6 +2277,7 @@ dependencies = [
"backtrace",
"bincode",
"colors-transform",
+ "daemonize",
"directories-next",
"futures",
"insta",
diff --git a/Cargo.toml b/Cargo.toml
index 978c06533..099d17f6a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -15,6 +15,7 @@ include = ["src/**/*", "assets/plugins/*", "assets/layouts/*", "assets/config/*"
ansi_term = "0.12.1"
backtrace = "0.3.55"
bincode = "1.3.1"
+daemonize = "0.4.1"
directories-next = "2.0"
futures = "0.3.5"
libc = "0.2"
diff --git a/src/cli.rs b/src/cli.rs
index 69496808b..72666dd66 100644
--- a/src/cli.rs
+++ b/src/cli.rs
@@ -16,6 +16,9 @@ pub struct CliArgs {
#[structopt(long)]
pub data_dir: Option<PathBuf>,
+ #[structopt(long)]
+ pub server: Option<PathBuf>,
+
/// Path to a layout yaml file
#[structopt(short, long)]
pub layout: Option<PathBuf>,
diff --git a/src/client/mod.rs b/src/client/mod.rs
index 6f298615f..d24b66d3a 100644
--- a/src/client/mod.rs
+++ b/src/client/mod.rs
@@ -5,7 +5,10 @@ pub mod panes;
pub mod tab;
use serde::{Deserialize, Serialize};
-use std::io::Write;
+use std::env::current_exe;
+use std::io::{self, Write};
+use std::path::Path;
+use std::process::Command;
use std::sync::mpsc;
use std::thread;
@@ -18,6 +21,7 @@ use crate::common::{
input::options::Options,
os_input_output::ClientOsApi,
thread_bus::{SenderType, SenderWithContext, SyncChannelWithContext},
+ utils::consts::ZELLIJ_IPC_PIPE,
};
use crate::server::ServerInstruction;
@@ -30,8 +34,25 @@ pub enum ClientInstruction {
Exit,
}
+fn spawn_server(socket_path: &Path) -> io::Result<()> {
+ let status = Command::new(current_exe()?)
+ .arg("--server")
+ .arg(socket_path)
+ .status()?;
+ if status.success() {
+ Ok(())
+ } else {
+ let msg = "Process returned non-zero exit code";
+ let err_msg = match status.code() {
+ Some(c) => format!("{}: {}", msg, c),
+ None => msg.to_string(),
+ };
+ Err(io::Error::new(io::ErrorKind::Other, err_msg))
+ }
+}
+
pub fn start_client(mut os_input: Box<dyn ClientOsApi>, opts: CliArgs, config: Config) {
- let clear_client_terminal_attributes = "\u{1b}[?1l\u{1b}=\u{1b}[r\u{1b}12l\u{1b}[?1000l\u{1b}[?1002l\u{1b}[?1003l\u{1b}[?1005l\u{1b}[?1006l\u{1b}[?12l";
+ spawn_server(&*ZELLIJ_IPC_PIPE).unwrap();
let take_snapshot = "\u{1b}[?1049h";
let bracketed_paste = "\u{1b}[?2004h";
os_input.unset_raw_mode(0);
@@ -50,12 +71,8 @@ pub fn start_client(mut os_input: Box<dyn ClientOsApi>, opts: CliArgs, config: C
let config_options = Options::from_cli(&config.options, opts.option.clone());
let full_screen_ws = os_input.get_terminal_size_using_fd(0);
- os_input.connect_to_server();
- os_input.send_to_server(ServerInstruction::NewClient(
- full_screen_ws,
- opts,
- config_options,
- ));
+ os_input.connect_to_server(&*ZELLIJ_IPC_PIPE);
+ os_input.send_to_server(ServerInstruction::NewClient(full_screen_ws, opts));
os_input.set_raw_mode(0);
let _ = os_input
.get_stdout_writer()
@@ -130,7 +147,6 @@ pub fn start_client(mut os_input: Box<dyn ClientOsApi>, opts: CliArgs, config: C
})
.unwrap();
- #[warn(clippy::never_loop)]
loop {
let (client_instruction, mut err_ctx) = receive_client_instructions
.recv()
diff --git a/src/common/os_input_output.rs b/src/common/os_input_output.rs
index 6f891e0d5..2a9a14e07 100644
--- a/src/common/os_input_output.rs
+++ b/src/common/os_input_output.rs
@@ -1,8 +1,5 @@
use crate::client::ClientInstruction;
-use crate::common::{
- ipc::{IpcReceiverWithContext, IpcSenderWithContext},
- utils::consts::ZELLIJ_IPC_PIPE,
-};
+use crate::common::ipc::{IpcReceiverWithContext, IpcSenderWithContext};
use crate::errors::ErrorContext;
use crate::panes::PositionAndSize;
use crate::server::ServerInstruction;
@@ -319,7 +316,7 @@ pub trait ClientOsApi: Send + Sync {
fn recv_from_server(&self) -> (ClientInstruction, ErrorContext);
fn receive_sigwinch(&self, cb: Box<dyn Fn()>);
/// Establish a connection with the server socket.
- fn connect_to_server(&self);
+ fn connect_to_server(&self, path: &Path);
}
impl ClientOsApi for ClientOsInputOutput {
@@ -379,14 +376,19 @@ impl ClientOsApi for ClientOsInputOutput {
}
}
}
- fn connect_to_server(&self) {
- let socket = match LocalSocketStream::connect(&**ZELLIJ_IPC_PIPE) {
- Ok(sock) => sock,
- Err(_) => {
- std::thread::sleep(std::time::Duration::from_millis(20));
- LocalSocketStream::connect(&**ZELLIJ_IPC_PIPE).unwrap()
+ fn connect_to_server(&self, path: &Path) {
+ let socket;
+ loop {
+ match LocalSocketStream::connect(path) {
+ Ok(sock) => {
+ socket = sock;
+ break;
+ }
+ Err(_) => {
+ std::thread::sleep(std::time::Duration::from_millis(50));
+ }
}
- };
+ }
let sender = IpcSenderWithContext::new(socket);
let receiver = sender.get_receiver();
*self.send_instructions_to_server.lock().unwrap() = Some(sender);
diff --git a/src/main.rs b/src/main.rs
index c1f0f387d..d08deb4af 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -17,7 +17,7 @@ use crate::command_is_executing::CommandIsExecuting;
use crate::common::input::{config::Config, options::Options};
use crate::os_input_output::{get_client_os_input, get_server_os_input, ClientOsApi, ServerOsApi};
use crate::utils::{
- consts::{ZELLIJ_TMP_DIR, ZELLIJ_TMP_LOG_DIR},
+ consts::{ZELLIJ_IPC_PIPE, ZELLIJ_TMP_DIR, ZELLIJ_TMP_LOG_DIR},
logging::*,
};
use std::convert::TryFrom;
@@ -39,15 +39,13 @@ pub fn main() {
let config_options = Options::from_cli(&config.options, opts.option.clone());
atomic_create_dir(&*ZELLIJ_TMP_DIR).unwrap();
atomic_create_dir(&*ZELLIJ_TMP_LOG_DIR).unwrap();
- let server_os_input = get_server_os_input();
- let os_input = get_client_os_input();
- start(
- Box::new(os_input),
- opts,
- Box::new(server_os_input),
- config,
- config_options,
- );
+ if let Some(path) = opts.server {
+ let os_input = get_server_os_input();
+ start_server(Box::new(os_input), path);
+ } else {
+ let os_input = get_client_os_input();
+ start_client(Box::new(os_input), opts, config);
+ }
}
}
pub fn start(
@@ -57,7 +55,7 @@ pub fn start(
config: Config,
config_options: Options,
) {
- let ipc_thread = start_server(server_os_input, config_options);
+ start_server(server_os_input, ZELLIJ_IPC_PIPE.clone());
start_client(client_os_input, opts, config);
- drop(ipc_thread.join());
+ //drop(ipc_thread.join());
}
diff --git a/src/server/mod.rs b/src/server/mod.rs
index 149e2dbd0..f85a4c7f2 100644
--- a/src/server/mod.rs
+++ b/src/server/mod.rs
@@ -1,5 +1,6 @@
pub mod route;
+use daemonize::Daemonize;
use interprocess::local_socket::LocalSocketListener;
use serde::{Deserialize, Serialize};
use std::sync::{Arc, RwLock};
@@ -19,7 +20,7 @@ use crate::common::{
screen::{screen_thread_main, ScreenInstruction},
setup::{get_default_data_dir, install::populate_data_dir},
thread_bus::{ChannelWithContext, SenderType, SenderWithContext},
- utils::consts::ZELLIJ_IPC_PIPE,
+ utils::consts::ZELLIJ_PROJ_DIR,
wasm_vm::{wasm_thread_main, PluginInstruction},
};
use crate::layout::Layout;
@@ -56,10 +57,12 @@ impl Drop for SessionMetaData {
}
}
-pub fn start_server(
- os_input: Box<dyn ServerOsApi>,
- config_options: Options,
-) -> thread::JoinHandle<()> {
+pub fn start_server(os_input: Box<dyn ServerOsApi>, socket_path: PathBuf) {
+ Daemonize::new()
+ .working_directory(std::env::var("HOME").unwrap())
+ .umask(0o077)
+ .start()
+ .expect("could not daemonize the server process");
let (to_server, server_receiver): ChannelWithContext<ServerInstruction> = channel();
let to_server = SenderWithContext::new(SenderType::Sender(to_server));
let sessions: Arc<RwLock<Option<SessionMetaData>>> = Arc::new(RwLock::new(None));
@@ -85,13 +88,11 @@ pub fn start_server(
let os_input = os_input.clone();
let sessions = sessions.clone();
let to_server = to_server.clone();
- let capabilities = PluginCapabilities {
- arrow_fonts: config_options.simplified_ui,
- };
+ let socket_path = socket_path.clone();
move || {
- drop(std::fs::remove_file(&*ZELLIJ_IPC_PIPE));
- let listener = LocalSocketListener::bind(&**ZELLIJ_IPC_PIPE).unwrap();
- set_permissions(&*ZELLIJ_IPC_PIPE).unwrap();
+ drop(std::fs::remove_file(&socket_path));
+ let listener = LocalSocketListener::bind(&*socket_path).unwrap();
+ set_permissions(&socket_path).unwrap();
for stream in listener.incoming() {
match stream {
Ok(stream) => {
@@ -125,48 +126,38 @@ pub fn start_server(
}
});
- thread::Builder::new()
- .name("server_thread".to_string())
- .spawn({
- move || loop {
- let (instruction, mut err_ctx) = server_receiver.recv().unwrap();
- err_ctx.add_call(ContextType::IPCServer(ServerContext::from(&instruction)));
- match instruction {
- ServerInstruction::NewClient(full_screen_ws, opts, config_options) => {
- let session_data = init_session(
- os_input.clone(),
- opts,
- config_options,
- to_server.clone(),
- full_screen_ws,
- );
- *sessions.write().unwrap() = Some(session_data);
- sessions
- .read()
- .unwrap()
- .as_ref()
- .unwrap()
- .senders
- .send_to_pty(PtyInstruction::NewTab)
- .unwrap();
- }
- ServerInstruction::UnblockInputThread => {
- os_input.send_to_client(ClientInstruction::UnblockInputThread);
- }
- ServerInstruction::ClientExit => {
- *sessions.write().unwrap() = None;
- os_input.send_to_client(ClientInstruction::Exit);
- drop(std::fs::remove_file(&*ZELLIJ_IPC_PIPE));
- break;
- }
- ServerInstruction::Render(output) => {
- os_input.send_to_client(ClientInstruction::Render(output))
- }
- _ => panic!("Received unexpected instruction."),
- }
+ loop {
+ let (instruction, mut err_ctx) = server_receiver.recv().unwrap();
+ err_ctx.add_call(ContextType::IPCServer(ServerContext::from(&instruction)));
+ match instruction {
+ ServerInstruction::NewClient(full_screen_ws, opts) => {
+ let session_data =
+ init_session(os_input.clone(), opts, to_server.clone(), full_screen_ws);
+ *sessions.write().unwrap() = Some(session_data);
+ sessions
+ .read()
+ .unwrap()
+ .as_ref()
+ .unwrap()
+ .senders
+ .send_to_pty(PtyInstruction::NewTab)
+ .unwrap();
}
- })
- .unwrap()
+ ServerInstruction::UnblockInputThread => {
+ os_input.send_to_client(ClientInstruction::UnblockInputThread);
+ }
+ ServerInstruction::ClientExit => {
+ *sessions.write().unwrap() = None;
+ os_input.send_to_client(ClientInstruction::Exit);
+ drop(std::fs::remove_file(&socket_path));
+ break;
+ }
+ ServerInstruction::Render(output) => {
+ os_input.send_to_client(ClientInstruction::Render(output))
+ }
+ _ => panic!("Received unexpected instruction."),
+ }
+ }
}
fn init_session(
diff --git a/src/tests/fakes.rs b/src/tests/fakes.rs
index eb0d14e86..1697e65f7 100644
--- a/src/tests/fakes.rs
+++ b/src/tests/fakes.rs
@@ -217,7 +217,7 @@ impl ClientOsApi for FakeInputOutput {
cb();
}
}
- fn connect_to_server(&self) {}
+ fn connect_to_server(&self, path: &std::path::Path) {}
}
impl ServerOsApi for FakeInputOutput {