Switch to multiprocess model: Not looking good
This commit is contained in:
parent
20d4b1826d
commit
0d792e26f2
8 changed files with 114 additions and 86 deletions
17
Cargo.lock
generated
17
Cargo.lock
generated
|
|
@ -248,6 +248,12 @@ dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "boxfnonce"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5988cb1d626264ac94100be357308f29ff7cbdd3b36bda27f450a4ee3f713426"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bumpalo"
|
name = "bumpalo"
|
||||||
version = "3.6.1"
|
version = "3.6.1"
|
||||||
|
|
@ -467,6 +473,16 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "daemonize"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "70c24513e34f53b640819f0ac9f705b673fcf4006d7aab8778bee72ebfc89815"
|
||||||
|
dependencies = [
|
||||||
|
"boxfnonce",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "darling"
|
name = "darling"
|
||||||
version = "0.12.3"
|
version = "0.12.3"
|
||||||
|
|
@ -2261,6 +2277,7 @@ dependencies = [
|
||||||
"backtrace",
|
"backtrace",
|
||||||
"bincode",
|
"bincode",
|
||||||
"colors-transform",
|
"colors-transform",
|
||||||
|
"daemonize",
|
||||||
"directories-next",
|
"directories-next",
|
||||||
"futures",
|
"futures",
|
||||||
"insta",
|
"insta",
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ include = ["src/**/*", "assets/plugins/*", "assets/layouts/*", "assets/config/*"
|
||||||
ansi_term = "0.12.1"
|
ansi_term = "0.12.1"
|
||||||
backtrace = "0.3.55"
|
backtrace = "0.3.55"
|
||||||
bincode = "1.3.1"
|
bincode = "1.3.1"
|
||||||
|
daemonize = "0.4.1"
|
||||||
directories-next = "2.0"
|
directories-next = "2.0"
|
||||||
futures = "0.3.5"
|
futures = "0.3.5"
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,9 @@ pub struct CliArgs {
|
||||||
#[structopt(long)]
|
#[structopt(long)]
|
||||||
pub data_dir: Option<PathBuf>,
|
pub data_dir: Option<PathBuf>,
|
||||||
|
|
||||||
|
#[structopt(long)]
|
||||||
|
pub server: Option<PathBuf>,
|
||||||
|
|
||||||
/// Path to a layout yaml file
|
/// Path to a layout yaml file
|
||||||
#[structopt(short, long)]
|
#[structopt(short, long)]
|
||||||
pub layout: Option<PathBuf>,
|
pub layout: Option<PathBuf>,
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,10 @@ pub mod panes;
|
||||||
pub mod tab;
|
pub mod tab;
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
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::sync::mpsc;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
|
|
||||||
|
|
@ -18,6 +21,7 @@ use crate::common::{
|
||||||
input::options::Options,
|
input::options::Options,
|
||||||
os_input_output::ClientOsApi,
|
os_input_output::ClientOsApi,
|
||||||
thread_bus::{SenderType, SenderWithContext, SyncChannelWithContext},
|
thread_bus::{SenderType, SenderWithContext, SyncChannelWithContext},
|
||||||
|
utils::consts::ZELLIJ_IPC_PIPE,
|
||||||
};
|
};
|
||||||
use crate::server::ServerInstruction;
|
use crate::server::ServerInstruction;
|
||||||
|
|
||||||
|
|
@ -30,8 +34,25 @@ pub enum ClientInstruction {
|
||||||
Exit,
|
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) {
|
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 take_snapshot = "\u{1b}[?1049h";
|
||||||
let bracketed_paste = "\u{1b}[?2004h";
|
let bracketed_paste = "\u{1b}[?2004h";
|
||||||
os_input.unset_raw_mode(0);
|
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 config_options = Options::from_cli(&config.options, opts.option.clone());
|
||||||
|
|
||||||
let full_screen_ws = os_input.get_terminal_size_using_fd(0);
|
let full_screen_ws = os_input.get_terminal_size_using_fd(0);
|
||||||
os_input.connect_to_server();
|
os_input.connect_to_server(&*ZELLIJ_IPC_PIPE);
|
||||||
os_input.send_to_server(ServerInstruction::NewClient(
|
os_input.send_to_server(ServerInstruction::NewClient(full_screen_ws, opts));
|
||||||
full_screen_ws,
|
|
||||||
opts,
|
|
||||||
config_options,
|
|
||||||
));
|
|
||||||
os_input.set_raw_mode(0);
|
os_input.set_raw_mode(0);
|
||||||
let _ = os_input
|
let _ = os_input
|
||||||
.get_stdout_writer()
|
.get_stdout_writer()
|
||||||
|
|
@ -130,7 +147,6 @@ pub fn start_client(mut os_input: Box<dyn ClientOsApi>, opts: CliArgs, config: C
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
#[warn(clippy::never_loop)]
|
|
||||||
loop {
|
loop {
|
||||||
let (client_instruction, mut err_ctx) = receive_client_instructions
|
let (client_instruction, mut err_ctx) = receive_client_instructions
|
||||||
.recv()
|
.recv()
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,5 @@
|
||||||
use crate::client::ClientInstruction;
|
use crate::client::ClientInstruction;
|
||||||
use crate::common::{
|
use crate::common::ipc::{IpcReceiverWithContext, IpcSenderWithContext};
|
||||||
ipc::{IpcReceiverWithContext, IpcSenderWithContext},
|
|
||||||
utils::consts::ZELLIJ_IPC_PIPE,
|
|
||||||
};
|
|
||||||
use crate::errors::ErrorContext;
|
use crate::errors::ErrorContext;
|
||||||
use crate::panes::PositionAndSize;
|
use crate::panes::PositionAndSize;
|
||||||
use crate::server::ServerInstruction;
|
use crate::server::ServerInstruction;
|
||||||
|
|
@ -319,7 +316,7 @@ pub trait ClientOsApi: Send + Sync {
|
||||||
fn recv_from_server(&self) -> (ClientInstruction, ErrorContext);
|
fn recv_from_server(&self) -> (ClientInstruction, ErrorContext);
|
||||||
fn receive_sigwinch(&self, cb: Box<dyn Fn()>);
|
fn receive_sigwinch(&self, cb: Box<dyn Fn()>);
|
||||||
/// Establish a connection with the server socket.
|
/// Establish a connection with the server socket.
|
||||||
fn connect_to_server(&self);
|
fn connect_to_server(&self, path: &Path);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClientOsApi for ClientOsInputOutput {
|
impl ClientOsApi for ClientOsInputOutput {
|
||||||
|
|
@ -379,14 +376,19 @@ impl ClientOsApi for ClientOsInputOutput {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn connect_to_server(&self) {
|
fn connect_to_server(&self, path: &Path) {
|
||||||
let socket = match LocalSocketStream::connect(&**ZELLIJ_IPC_PIPE) {
|
let socket;
|
||||||
Ok(sock) => sock,
|
loop {
|
||||||
Err(_) => {
|
match LocalSocketStream::connect(path) {
|
||||||
std::thread::sleep(std::time::Duration::from_millis(20));
|
Ok(sock) => {
|
||||||
LocalSocketStream::connect(&**ZELLIJ_IPC_PIPE).unwrap()
|
socket = sock;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
std::thread::sleep(std::time::Duration::from_millis(50));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
let sender = IpcSenderWithContext::new(socket);
|
let sender = IpcSenderWithContext::new(socket);
|
||||||
let receiver = sender.get_receiver();
|
let receiver = sender.get_receiver();
|
||||||
*self.send_instructions_to_server.lock().unwrap() = Some(sender);
|
*self.send_instructions_to_server.lock().unwrap() = Some(sender);
|
||||||
|
|
|
||||||
22
src/main.rs
22
src/main.rs
|
|
@ -17,7 +17,7 @@ use crate::command_is_executing::CommandIsExecuting;
|
||||||
use crate::common::input::{config::Config, options::Options};
|
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::os_input_output::{get_client_os_input, get_server_os_input, ClientOsApi, ServerOsApi};
|
||||||
use crate::utils::{
|
use crate::utils::{
|
||||||
consts::{ZELLIJ_TMP_DIR, ZELLIJ_TMP_LOG_DIR},
|
consts::{ZELLIJ_IPC_PIPE, ZELLIJ_TMP_DIR, ZELLIJ_TMP_LOG_DIR},
|
||||||
logging::*,
|
logging::*,
|
||||||
};
|
};
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
|
@ -39,15 +39,13 @@ pub fn main() {
|
||||||
let config_options = Options::from_cli(&config.options, opts.option.clone());
|
let config_options = Options::from_cli(&config.options, opts.option.clone());
|
||||||
atomic_create_dir(&*ZELLIJ_TMP_DIR).unwrap();
|
atomic_create_dir(&*ZELLIJ_TMP_DIR).unwrap();
|
||||||
atomic_create_dir(&*ZELLIJ_TMP_LOG_DIR).unwrap();
|
atomic_create_dir(&*ZELLIJ_TMP_LOG_DIR).unwrap();
|
||||||
let server_os_input = get_server_os_input();
|
if let Some(path) = opts.server {
|
||||||
let os_input = get_client_os_input();
|
let os_input = get_server_os_input();
|
||||||
start(
|
start_server(Box::new(os_input), path);
|
||||||
Box::new(os_input),
|
} else {
|
||||||
opts,
|
let os_input = get_client_os_input();
|
||||||
Box::new(server_os_input),
|
start_client(Box::new(os_input), opts, config);
|
||||||
config,
|
}
|
||||||
config_options,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn start(
|
pub fn start(
|
||||||
|
|
@ -57,7 +55,7 @@ pub fn start(
|
||||||
config: Config,
|
config: Config,
|
||||||
config_options: Options,
|
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);
|
start_client(client_os_input, opts, config);
|
||||||
drop(ipc_thread.join());
|
//drop(ipc_thread.join());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
pub mod route;
|
pub mod route;
|
||||||
|
|
||||||
|
use daemonize::Daemonize;
|
||||||
use interprocess::local_socket::LocalSocketListener;
|
use interprocess::local_socket::LocalSocketListener;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
@ -19,7 +20,7 @@ use crate::common::{
|
||||||
screen::{screen_thread_main, ScreenInstruction},
|
screen::{screen_thread_main, ScreenInstruction},
|
||||||
setup::{get_default_data_dir, install::populate_data_dir},
|
setup::{get_default_data_dir, install::populate_data_dir},
|
||||||
thread_bus::{ChannelWithContext, SenderType, SenderWithContext},
|
thread_bus::{ChannelWithContext, SenderType, SenderWithContext},
|
||||||
utils::consts::ZELLIJ_IPC_PIPE,
|
utils::consts::ZELLIJ_PROJ_DIR,
|
||||||
wasm_vm::{wasm_thread_main, PluginInstruction},
|
wasm_vm::{wasm_thread_main, PluginInstruction},
|
||||||
};
|
};
|
||||||
use crate::layout::Layout;
|
use crate::layout::Layout;
|
||||||
|
|
@ -56,10 +57,12 @@ impl Drop for SessionMetaData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start_server(
|
pub fn start_server(os_input: Box<dyn ServerOsApi>, socket_path: PathBuf) {
|
||||||
os_input: Box<dyn ServerOsApi>,
|
Daemonize::new()
|
||||||
config_options: Options,
|
.working_directory(std::env::var("HOME").unwrap())
|
||||||
) -> thread::JoinHandle<()> {
|
.umask(0o077)
|
||||||
|
.start()
|
||||||
|
.expect("could not daemonize the server process");
|
||||||
let (to_server, server_receiver): ChannelWithContext<ServerInstruction> = channel();
|
let (to_server, server_receiver): ChannelWithContext<ServerInstruction> = channel();
|
||||||
let to_server = SenderWithContext::new(SenderType::Sender(to_server));
|
let to_server = SenderWithContext::new(SenderType::Sender(to_server));
|
||||||
let sessions: Arc<RwLock<Option<SessionMetaData>>> = Arc::new(RwLock::new(None));
|
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 os_input = os_input.clone();
|
||||||
let sessions = sessions.clone();
|
let sessions = sessions.clone();
|
||||||
let to_server = to_server.clone();
|
let to_server = to_server.clone();
|
||||||
let capabilities = PluginCapabilities {
|
let socket_path = socket_path.clone();
|
||||||
arrow_fonts: config_options.simplified_ui,
|
|
||||||
};
|
|
||||||
move || {
|
move || {
|
||||||
drop(std::fs::remove_file(&*ZELLIJ_IPC_PIPE));
|
drop(std::fs::remove_file(&socket_path));
|
||||||
let listener = LocalSocketListener::bind(&**ZELLIJ_IPC_PIPE).unwrap();
|
let listener = LocalSocketListener::bind(&*socket_path).unwrap();
|
||||||
set_permissions(&*ZELLIJ_IPC_PIPE).unwrap();
|
set_permissions(&socket_path).unwrap();
|
||||||
for stream in listener.incoming() {
|
for stream in listener.incoming() {
|
||||||
match stream {
|
match stream {
|
||||||
Ok(stream) => {
|
Ok(stream) => {
|
||||||
|
|
@ -125,48 +126,38 @@ pub fn start_server(
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
thread::Builder::new()
|
loop {
|
||||||
.name("server_thread".to_string())
|
let (instruction, mut err_ctx) = server_receiver.recv().unwrap();
|
||||||
.spawn({
|
err_ctx.add_call(ContextType::IPCServer(ServerContext::from(&instruction)));
|
||||||
move || loop {
|
match instruction {
|
||||||
let (instruction, mut err_ctx) = server_receiver.recv().unwrap();
|
ServerInstruction::NewClient(full_screen_ws, opts) => {
|
||||||
err_ctx.add_call(ContextType::IPCServer(ServerContext::from(&instruction)));
|
let session_data =
|
||||||
match instruction {
|
init_session(os_input.clone(), opts, to_server.clone(), full_screen_ws);
|
||||||
ServerInstruction::NewClient(full_screen_ws, opts, config_options) => {
|
*sessions.write().unwrap() = Some(session_data);
|
||||||
let session_data = init_session(
|
sessions
|
||||||
os_input.clone(),
|
.read()
|
||||||
opts,
|
.unwrap()
|
||||||
config_options,
|
.as_ref()
|
||||||
to_server.clone(),
|
.unwrap()
|
||||||
full_screen_ws,
|
.senders
|
||||||
);
|
.send_to_pty(PtyInstruction::NewTab)
|
||||||
*sessions.write().unwrap() = Some(session_data);
|
.unwrap();
|
||||||
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."),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
ServerInstruction::UnblockInputThread => {
|
||||||
.unwrap()
|
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(
|
fn init_session(
|
||||||
|
|
|
||||||
|
|
@ -217,7 +217,7 @@ impl ClientOsApi for FakeInputOutput {
|
||||||
cb();
|
cb();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn connect_to_server(&self) {}
|
fn connect_to_server(&self, path: &std::path::Path) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerOsApi for FakeInputOutput {
|
impl ServerOsApi for FakeInputOutput {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue