summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordenis <denismaximov98@gmail.com>2021-03-18 12:20:23 +0200
committerKunal Mohan <kunalmohan99@gmail.com>2021-04-14 01:41:29 +0530
commit1f0e2ea29ed31008e4c4fa2e259d4fd7e415a483 (patch)
tree31cd569f325275eb772b69ebe8c519184dc8a9e9
parent2df0585430e551b422145621bc52936f8a5230bc (diff)
wip: here goes the os_thread and OsContext
-rw-r--r--src/common/errors.rs41
-rw-r--r--src/server/mod.rs407
2 files changed, 270 insertions, 178 deletions
diff --git a/src/common/errors.rs b/src/common/errors.rs
index d30af844a..4fd8b2aa7 100644
--- a/src/common/errors.rs
+++ b/src/common/errors.rs
@@ -1,7 +1,7 @@
//! Error context system based on a thread-local representation of the call stack, itself based on
//! the instructions that are sent between threads.
-use super::{AppInstruction, ASYNCOPENCALLS, OPENCALLS};
+use super::{os_input_output::OsApiInstruction, AppInstruction, OPENCALLS};
use crate::pty_bus::PtyInstruction;
use crate::screen::ScreenInstruction;
use serde::{Deserialize, Serialize};
@@ -138,6 +138,8 @@ pub enum ContextType {
Screen(ScreenContext),
/// A PTY-related call.
Pty(PtyContext),
+ /// An OS-related call.
+ Os(OsContext),
/// A plugin-related call.
Plugin(PluginContext),
/// An app-related call.
@@ -158,7 +160,7 @@ impl Display for ContextType {
match *self {
ContextType::Screen(c) => write!(f, "{}screen_thread: {}{:?}", purple, green, c),
ContextType::Pty(c) => write!(f, "{}pty_thread: {}{:?}", purple, green, c),
-
+ ContextType::Os(c) => write!(f, "{}os_thread: {}{:?}", purple, green, c),
ContextType::Plugin(c) => write!(f, "{}plugin_thread: {}{:?}", purple, green, c),
ContextType::App(c) => write!(f, "{}main_thread: {}{:?}", purple, green, c),
ContextType::IpcServer => write!(f, "{}ipc_server: {}AcceptInput", purple, green),
@@ -287,6 +289,41 @@ impl From<&PtyInstruction> for PtyContext {
}
}
+#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
+pub enum OsContext {
+ SpawnTerminal,
+ GetTerminalSizeUsingFd,
+ SetTerminalSizeUsingFd,
+ SetRawMode,
+ UnsetRawMode,
+ ReadFromTtyStdout,
+ WriteToTtyStdin,
+ TcDrain,
+ Kill,
+ ReadFromStdin,
+ GetStdoutWriter,
+ BoxClone,
+}
+
+impl From<&OsApiInstruction> for OsContext {
+ fn from(os_instruction: &OsApiInstruction) -> Self {
+ match *os_instruction {
+ OsApiInstruction::SpawnTerminal(_) => OsContext::SpawnTerminal,
+ OsApiInstruction::GetTerminalSizeUsingFd(_) => OsContext::GetTerminalSizeUsingFd,
+ OsApiInstruction::SetTerminalSizeUsingFd(_, _, _) => OsContext::SetTerminalSizeUsingFd,
+ OsApiInstruction::SetRawMode(_) => OsContext::SetRawMode,
+ OsApiInstruction::UnsetRawMode(_) => OsContext::UnsetRawMode,
+ OsApiInstruction::ReadFromTtyStdout(_, _) => OsContext::ReadFromTtyStdout,
+ OsApiInstruction::WriteToTtyStdin(_, _) => OsContext::WriteToTtyStdin,
+ OsApiInstruction::TcDrain(_) => OsContext::TcDrain,
+ OsApiInstruction::Kill(_) => OsContext::Kill,
+ OsApiInstruction::ReadFromStdin => OsContext::ReadFromStdin,
+ OsApiInstruction::GetStdoutWriter => OsContext::GetStdoutWriter,
+ OsApiInstruction::BoxClone => OsContext::BoxClone
+ }
+ }
+}
+
// FIXME: This whole pattern *needs* a macro eventually, it's soul-crushing to write
use crate::wasm_vm::PluginInstruction;
diff --git a/src/server/mod.rs b/src/server/mod.rs
index 794066b05..3ca9e0043 100644
--- a/src/server/mod.rs
+++ b/src/server/mod.rs
@@ -1,9 +1,9 @@
use crate::cli::CliArgs;
use crate::common::{
- ChannelWithContext, ClientInstruction, IpcSenderWithContext, SenderType, SenderWithContext,
- ServerInstruction,
+ ChannelWithContext, ClientInstruction, IpcSenderWithContext, SenderType, SenderWithContext,
+ ServerInstruction,
};
-use crate::errors::{ContextType, ErrorContext, PtyContext};
+use crate::errors::{ContextType, ErrorContext, OsContext, PtyContext};
use crate::os_input_output::{OsApi, OsApiInstruction};
use crate::panes::PaneId;
use crate::pty_bus::{PtyBus, PtyInstruction};
@@ -15,185 +15,240 @@ use std::sync::mpsc::channel;
use std::thread;
pub fn start_server(os_input: Box<dyn OsApi>, opts: CliArgs) -> (thread::JoinHandle<()>, String) {
- let (send_pty_instructions, receive_pty_instructions): ChannelWithContext<PtyInstruction> =
- channel();
- let mut send_pty_instructions = SenderWithContext::new(
- ErrorContext::new(),
- SenderType::Sender(send_pty_instructions),
- );
+ let (send_pty_instructions, receive_pty_instructions): ChannelWithContext<PtyInstruction> =
+ channel();
+ let mut send_pty_instructions = SenderWithContext::new(
+ ErrorContext::new(),
+ SenderType::Sender(send_pty_instructions),
+ );
- #[cfg(not(test))]
- let (server_name, server_buffer) = (
- String::from(ZELLIJ_IPC_PIPE),
- SharedRingBuffer::create(ZELLIJ_IPC_PIPE, 8192).unwrap(),
- );
- #[cfg(test)]
- let (server_name, server_buffer) = SharedRingBuffer::create_temp(8192).unwrap();
+ #[cfg(not(test))]
+ let (server_name, server_buffer) = (
+ String::from(ZELLIJ_IPC_PIPE),
+ SharedRingBuffer::create(ZELLIJ_IPC_PIPE, 8192).unwrap(),
+ );
+ #[cfg(test)]
+ let (server_name, server_buffer) = SharedRingBuffer::create_temp(8192).unwrap();
- let (send_os_instructions, receive_os_instructions): ChannelWithContext<OsApiInstruction> = channel();
- let mut send_os_instructions = SenderWithContext::new(
- ErrorContext::new(),
- SenderType::Sender(send_os_instructions),
- );
+ let (send_os_instructions, receive_os_instructions): ChannelWithContext<OsApiInstruction> =
+ channel();
+ let mut send_os_instructions = SenderWithContext::new(
+ ErrorContext::new(),
+ SenderType::Sender(send_os_instructions),
+ );
- // Don't use default layouts in tests, but do everywhere else
- #[cfg(not(test))]
- let default_layout = Some(PathBuf::from("default"));
- #[cfg(test)]
- let default_layout = None;
- let maybe_layout = opts.layout.or(default_layout);
+ // Don't use default layouts in tests, but do everywhere else
+ #[cfg(not(test))]
+ let default_layout = Some(PathBuf::from("default"));
+ #[cfg(test)]
+ let default_layout = None;
+ let maybe_layout = opts.layout.or(default_layout);
- let send_server_instructions = IpcSenderWithContext::new(server_buffer.clone());
+ let send_server_instructions = IpcSenderWithContext::new(server_buffer.clone());
- let mut pty_bus = PtyBus::new(
- receive_pty_instructions,
- os_input.clone(),
- send_server_instructions,
- opts.debug,
- );
+ let mut pty_bus = PtyBus::new(
+ receive_pty_instructions,
+ os_input.clone(),
+ send_server_instructions,
+ opts.debug,
+ );
- let pty_thread = thread::Builder::new()
- .name("pty".to_string())
- .spawn(move || loop {
- let (event, mut err_ctx) = pty_bus
- .receive_pty_instructions
- .recv()
- .expect("failed to receive event on channel");
- err_ctx.add_call(ContextType::Pty(PtyContext::from(&event)));
- match event {
- PtyInstruction::SpawnTerminal(file_to_open) => {
- let pid = pty_bus.spawn_terminal(file_to_open);
- pty_bus
- .send_server_instructions
- .send(ServerInstruction::ToScreen(ScreenInstruction::NewPane(
- PaneId::Terminal(pid),
- )))
- .unwrap();
- }
- PtyInstruction::SpawnTerminalVertically(file_to_open) => {
- let pid = pty_bus.spawn_terminal(file_to_open);
- pty_bus
- .send_server_instructions
- .send(ServerInstruction::ToScreen(
- ScreenInstruction::VerticalSplit(PaneId::Terminal(pid)),
- ))
- .unwrap();
- }
- PtyInstruction::SpawnTerminalHorizontally(file_to_open) => {
- let pid = pty_bus.spawn_terminal(file_to_open);
- pty_bus
- .send_server_instructions
- .send(ServerInstruction::ToScreen(
- ScreenInstruction::HorizontalSplit(PaneId::Terminal(pid)),
- ))
- .unwrap();
- }
- PtyInstruction::NewTab => {
- if let Some(layout) = maybe_layout.clone() {
- pty_bus.spawn_terminals_for_layout(layout);
- } else {
- let pid = pty_bus.spawn_terminal(None);
- pty_bus
- .send_server_instructions
- .send(ServerInstruction::ToScreen(ScreenInstruction::NewTab(pid)))
- .unwrap();
- }
- }
- PtyInstruction::ClosePane(id) => {
- pty_bus.close_pane(id);
- pty_bus
- .send_server_instructions
- .send(ServerInstruction::DoneClosingPane)
- .unwrap();
- }
- PtyInstruction::CloseTab(ids) => {
- pty_bus.close_tab(ids);
- pty_bus
- .send_server_instructions
- .send(ServerInstruction::DoneClosingPane)
- .unwrap();
- }
- PtyInstruction::Exit => {
- break;
- }
- }
- })
- .unwrap();
+ let pty_thread = thread::Builder::new()
+ .name("pty".to_string())
+ .spawn(move || loop {
+ let (event, mut err_ctx) = pty_bus
+ .receive_pty_instructions
+ .recv()
+ .expect("failed to receive event on channel");
+ err_ctx.add_call(ContextType::Pty(PtyContext::from(&event)));
+ match event {
+ PtyInstruction::SpawnTerminal(file_to_open) => {
+ let pid = pty_bus.spawn_terminal(file_to_open);
+ pty_bus
+ .send_server_instructions
+ .send(ServerInstruction::ToScreen(ScreenInstruction::NewPane(
+ PaneId::Terminal(pid),
+ )))
+ .unwrap();
+ }
+ PtyInstruction::SpawnTerminalVertically(file_to_open) => {
+ let pid = pty_bus.spawn_terminal(file_to_open);
+ pty_bus
+ .send_server_instructions
+ .send(ServerInstruction::ToScreen(
+ ScreenInstruction::VerticalSplit(PaneId::Terminal(pid)),
+ ))
+ .unwrap();
+ }
+ PtyInstruction::SpawnTerminalHorizontally(file_to_open) => {
+ let pid = pty_bus.spawn_terminal(file_to_open);
+ pty_bus
+ .send_server_instructions
+ .send(ServerInstruction::ToScreen(
+ ScreenInstruction::HorizontalSplit(PaneId::Terminal(pid)),
+ ))
+ .unwrap();
+ }
+ PtyInstruction::NewTab => {
+ if let Some(layout) = maybe_layout.clone() {
+ pty_bus.spawn_terminals_for_layout(layout);
+ } else {
+ let pid = pty_bus.spawn_terminal(None);
+ pty_bus
+ .send_server_instructions
+ .send(ServerInstruction::ToScreen(ScreenInstruction::NewTab(pid)))
+ .unwrap();
+ }
+ }
+ PtyInstruction::ClosePane(id) => {
+ pty_bus.close_pane(id);
+ pty_bus
+ .send_server_instructions
+ .send(ServerInstruction::DoneClosingPane)
+ .unwrap();
+ }
+ PtyInstruction::CloseTab(ids) => {
+ pty_bus.close_tab(ids);
+ pty_bus
+ .send_server_instructions
+ .send(ServerInstruction::DoneClosingPane)
+ .unwrap();
+ }
+ PtyInstruction::Exit => {
+ break;
+ }
+ }
+ })
+ .unwrap();
- let join_handle = thread::Builder::new()
- .name("ipc_server".to_string())
- .spawn({
- let recv_server_instructions = IpcReceiver::new(server_buffer);
- // Fixme: We cannot use uninitialised sender, therefore this Vec.
- // For now, We make sure that the first message is `NewClient` so there are no out of bound panics.
- let mut send_client_instructions: Vec<IpcSenderWithContext> = Vec::with_capacity(1);
- move || loop {
- let (mut err_ctx, instruction): (ErrorContext, ServerInstruction) =
- recv_server_instructions.recv().unwrap();
- err_ctx.add_call(ContextType::IPCServer);
- send_pty_instructions.update(err_ctx);
- if send_client_instructions.len() == 1 {
- send_client_instructions[0].update(err_ctx);
- }
+ let os_thread = thread::Builder::new()
+ .name("os".to_string())
+ .spawn({
+ let mut os_input = os_input.clone();
+ move || loop {
+ let (event, mut err_ctx) = receive_os_instructions
+ .recv()
+ .expect("failed to receive an event on the channel");
+ err_ctx.add_call(ContextType::Os(OsContext::from(&event)));
+ match event {
+ OsApiInstruction::SpawnTerminal(file_to_open) => {
+ os_input.spawn_terminal(file_to_open);
+ }
+ OsApiInstruction::GetTerminalSizeUsingFd(fd) => {
+ os_input.get_terminal_size_using_fd(fd);
+ }
+ OsApiInstruction::SetTerminalSizeUsingFd(fd, cols, rows) => {
+ os_input.set_terminal_size_using_fd(fd, cols, rows);
+ }
+ OsApiInstruction::SetRawMode(fd) => {
+ os_input.set_raw_mode(fd);
+ }
+ OsApiInstruction::UnsetRawMode(fd) => {
+ os_input.unset_raw_mode(fd);
+ }
+ OsApiInstruction::ReadFromTtyStdout(fd, mut buf) => {
+ let slice = buf.as_mut_slice();
+ os_input.read_from_tty_stdout(fd, slice).unwrap();
+ }
+ OsApiInstruction::WriteToTtyStdin(fd, mut buf) => {
+ let slice = buf.as_mut_slice();
+ os_input.write_to_tty_stdin(fd, slice).unwrap();
+ }
+ OsApiInstruction::TcDrain(fd) => {
+ os_input.tcdrain(fd).unwrap();
+ }
+ OsApiInstruction::Kill(pid) => {
+ os_input.kill(pid).unwrap();
+ }
+ OsApiInstruction::ReadFromStdin => {
+ os_input.read_from_stdin();
+ }
+ OsApiInstruction::GetStdoutWriter => {
+ os_input.get_stdout_writer();
+ }
+ OsApiInstruction::BoxClone => {
+ os_input.box_clone();
+ }
+ }
+ }
+ })
+ .unwrap();
- match instruction {
- ServerInstruction::OpenFile(file_name) => {
- let path = PathBuf::from(file_name);
- send_pty_instructions
- .send(PtyInstruction::SpawnTerminal(Some(path)))
- .unwrap();
- }
- ServerInstruction::SplitHorizontally => {
- send_pty_instructions
- .send(PtyInstruction::SpawnTerminalHorizontally(None))
- .unwrap();
- }
- ServerInstruction::SplitVertically => {
- send_pty_instructions
- .send(PtyInstruction::SpawnTerminalVertically(None))
- .unwrap();
- }
- ServerInstruction::MoveFocus => {
- send_client_instructions[0]
- .send(ClientInstruction::ToScreen(ScreenInstruction::MoveFocus))
- .unwrap();
- }
- ServerInstruction::NewClient(buffer_path) => {
- send_pty_instructions.send(PtyInstruction::NewTab).unwrap();
- send_client_instructions.push(IpcSenderWithContext::new(
- SharedRingBuffer::open(&buffer_path).unwrap(),
- ));
- }
- ServerInstruction::ToPty(instr) => {
- send_pty_instructions.send(instr).unwrap();
- }
- ServerInstruction::ToScreen(instr) => {
- send_client_instructions[0]
- .send(ClientInstruction::ToScreen(instr))
- .unwrap();
- }
- ServerInstruction::OsApi(instr) => {
- send_os_instructions.send(instr).unwrap();
- }
- ServerInstruction::DoneClosingPane => {
- send_client_instructions[0]
- .send(ClientInstruction::DoneClosingPane)
- .unwrap();
- }
- ServerInstruction::ClosePluginPane(pid) => {
- send_client_instructions[0]
- .send(ClientInstruction::ClosePluginPane(pid))
- .unwrap();
- }
- ServerInstruction::Exit => {
- let _ = send_pty_instructions.send(PtyInstruction::Exit);
- let _ = pty_thread.join();
- let _ = send_client_instructions[0].send(ClientInstruction::Exit);
- break;
- }
- }
- }
- })
- .unwrap();
- (join_handle, server_name)
+ let join_handle = thread::Builder::new()
+ .name("ipc_server".to_string())
+ .spawn({
+ let recv_server_instructions = IpcReceiver::new(server_buffer);
+ // Fixme: We cannot use uninitialised sender, therefore this Vec.
+ // For now, We make sure that the first message is `NewClient` so there are no out of bound panics.
+ let mut send_client_instructions: Vec<IpcSenderWithContext> = Vec::with_capacity(1);
+ move || loop {
+ let (mut err_ctx, instruction): (ErrorContext, ServerInstruction) =
+ recv_server_instructions.recv().unwrap();
+ err_ctx.add_call(ContextType::IPCServer);
+ send_pty_instructions.update(err_ctx);
+ if send_client_instructions.len() == 1 {
+ send_client_instructions[0].update(err_ctx);
+ }
+
+ match instruction {
+ ServerInstruction::OpenFile(file_name) => {
+ let path = PathBuf::from(file_name);
+ send_pty_instructions
+ .send(PtyInstruction::SpawnTerminal(Some(path)))
+ .unwrap();
+ }
+ ServerInstruction::SplitHorizontally => {
+ send_pty_instructions
+ .send(PtyInstruction::SpawnTerminalHorizontally(None))
+ .unwrap();
+ }
+ ServerInstruction::SplitVertically => {
+ send_pty_instructions
+ .send(PtyInstruction::SpawnTerminalVertically(None))
+ .unwrap();
+ }
+ ServerInstruction::MoveFocus => {
+ send_client_instructions[0]
+ .send(ClientInstruction::ToScreen(ScreenInstruction::MoveFocus))
+ .unwrap();
+ }
+ ServerInstruction::NewClient(buffer_path) => {
+ send_pty_instructions.send(PtyInstruction::NewTab).unwrap();
+ send_client_instructions.push(IpcSenderWithContext::new(
+ SharedRingBuffer::open(&buffer_path).unwrap(),
+ ));
+ }
+ ServerInstruction::ToPty(instr) => {
+ send_pty_instructions.send(instr).unwrap();
+ }
+ ServerInstruction::ToScreen(instr) => {
+ send_client_instructions[0]
+ .send(ClientInstruction::ToScreen(instr))
+ .unwrap();
+ }
+ ServerInstruction::OsApi(instr) => {
+ send_os_instructions.send(instr).unwrap();
+ }
+ ServerInstruction::DoneClosingPane => {
+ send_client_instructions[0]
+ .send(ClientInstruction::DoneClosingPane)
+ .unwrap();
+ }
+ ServerInstruction::ClosePluginPane(pid) => {
+ send_client_instructions[0]
+ .send(ClientInstruction::ClosePluginPane(pid))
+ .unwrap();
+ }
+ ServerInstruction::Exit => {
+ let _ = send_pty_instructions.send(PtyInstruction::Exit);
+ let _ = pty_thread.join();
+ let _ = os_thread.join();
+ let _ = send_client_instructions[0].send(ClientInstruction::Exit);
+ break;
+ }
+ }
+ }
+ })
+ .unwrap();
+ (join_handle, server_name)
}