Skip to content

Commit

Permalink
refactor(plugins): fix plugin loading data flow (#1995)
Browse files Browse the repository at this point in the history
  • Loading branch information
imsnif authored Dec 6, 2022
1 parent c2a6156 commit b7adfcc
Show file tree
Hide file tree
Showing 20 changed files with 1,431 additions and 934 deletions.
26 changes: 17 additions & 9 deletions zellij-server/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ pub mod panes;
pub mod tab;

mod logging_pipe;
mod plugins;
mod pty;
mod pty_writer;
mod route;
mod screen;
mod terminal_bytes;
mod thread_bus;
mod ui;
mod wasm_vm;

use log::info;
use pty_writer::{pty_writer_main, PtyWriteInstruction};
Expand All @@ -29,10 +29,10 @@ use wasmer::Store;

use crate::{
os_input_output::ServerOsApi,
plugins::{plugin_thread_main, PluginInstruction},
pty::{pty_thread_main, Pty, PtyInstruction},
screen::{screen_thread_main, ScreenInstruction},
thread_bus::{Bus, ThreadSenders},
wasm_vm::{wasm_thread_main, PluginInstruction},
};
use route::route_thread_main;
use zellij_utils::{
Expand Down Expand Up @@ -108,7 +108,7 @@ pub(crate) struct SessionMetaData {
pub default_shell: Option<TerminalAction>,
screen_thread: Option<thread::JoinHandle<()>>,
pty_thread: Option<thread::JoinHandle<()>>,
wasm_thread: Option<thread::JoinHandle<()>>,
plugin_thread: Option<thread::JoinHandle<()>>,
pty_writer_thread: Option<thread::JoinHandle<()>>,
}

Expand All @@ -124,8 +124,8 @@ impl Drop for SessionMetaData {
if let Some(pty_thread) = self.pty_thread.take() {
let _ = pty_thread.join();
}
if let Some(wasm_thread) = self.wasm_thread.take() {
let _ = wasm_thread.join();
if let Some(plugin_thread) = self.plugin_thread.take() {
let _ = plugin_thread.join();
}
if let Some(pty_writer_thread) = self.pty_writer_thread.take() {
let _ = pty_writer_thread.join();
Expand Down Expand Up @@ -332,7 +332,7 @@ pub fn start_server(mut os_input: Box<dyn ServerOsApi>, socket_path: PathBuf) {
.as_ref()
.unwrap()
.senders
.send_to_pty(PtyInstruction::NewTab(
.send_to_screen(ScreenInstruction::NewTab(
default_shell.clone(),
tab_layout,
tab_name,
Expand Down Expand Up @@ -655,6 +655,7 @@ fn init_session(
let pty_thread = thread::Builder::new()
.name("pty".to_string())
.spawn({
let layout = layout.clone();
let pty = Pty::new(
Bus::new(
vec![pty_receiver],
Expand Down Expand Up @@ -700,7 +701,7 @@ fn init_session(
})
.unwrap();

let wasm_thread = thread::Builder::new()
let plugin_thread = thread::Builder::new()
.name("wasm".to_string())
.spawn({
let plugin_bus = Bus::new(
Expand All @@ -715,7 +716,14 @@ fn init_session(
let store = Store::default();

move || {
wasm_thread_main(plugin_bus, store, data_dir, plugins.unwrap_or_default()).fatal()
plugin_thread_main(
plugin_bus,
store,
data_dir,
plugins.unwrap_or_default(),
layout,
)
.fatal()
}
})
.unwrap();
Expand Down Expand Up @@ -750,7 +758,7 @@ fn init_session(
client_attributes,
screen_thread: Some(screen_thread),
pty_thread: Some(pty_thread),
wasm_thread: Some(wasm_thread),
plugin_thread: Some(plugin_thread),
pty_writer_thread: Some(pty_writer_thread),
}
}
2 changes: 1 addition & 1 deletion zellij-server/src/panes/floating_panes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ use crate::{
os_input_output::ServerOsApi,
output::{FloatingPanesStack, Output},
panes::{ActivePanes, PaneId},
plugins::PluginInstruction,
thread_bus::ThreadSenders,
ui::pane_contents_and_ui::PaneContentsAndUi,
wasm_vm::PluginInstruction,
ClientId,
};
use std::cell::RefCell;
Expand Down
2 changes: 1 addition & 1 deletion zellij-server/src/panes/plugin_pane.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ use std::time::Instant;

use crate::output::{CharacterChunk, SixelImageChunk};
use crate::panes::{grid::Grid, sixel::SixelImageStore, LinkHandler, PaneId};
use crate::plugins::PluginInstruction;
use crate::pty::VteBytes;
use crate::tab::Pane;
use crate::ui::pane_boundaries_frame::{FrameParams, PaneFrame};
use crate::wasm_vm::PluginInstruction;
use crate::ClientId;
use std::cell::RefCell;
use std::rc::Rc;
Expand Down
4 changes: 1 addition & 3 deletions zellij-server/src/panes/tiled_panes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ use crate::{
os_input_output::ServerOsApi,
output::Output,
panes::{ActivePanes, PaneId},
plugins::PluginInstruction,
tab::{Pane, MIN_TERMINAL_HEIGHT, MIN_TERMINAL_WIDTH},
thread_bus::ThreadSenders,
ui::boundaries::Boundaries,
ui::pane_contents_and_ui::PaneContentsAndUi,
wasm_vm::PluginInstruction,
ClientId,
};
use zellij_utils::{
Expand Down Expand Up @@ -346,9 +346,7 @@ impl TiledPanes {
self.reset_boundaries();
}
pub fn focus_pane_if_client_not_focused(&mut self, pane_id: PaneId, client_id: ClientId) {
log::info!("inside focus_pane_if_client_not_focused");
if self.active_panes.get(&client_id).is_none() {
log::info!("is none");
self.focus_pane(pane_id, client_id)
}
}
Expand Down
135 changes: 135 additions & 0 deletions zellij-server/src/plugins/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
mod wasm_bridge;
use log::info;
use std::{collections::HashMap, fs, path::PathBuf};
use wasmer::Store;

use crate::{pty::PtyInstruction, thread_bus::Bus, ClientId};

use wasm_bridge::WasmBridge;

use zellij_utils::{
data::Event,
errors::{prelude::*, ContextType, PluginContext},
input::{
command::TerminalAction,
layout::{Layout, PaneLayout, Run, RunPlugin, RunPluginLocation},
plugins::PluginsConfig,
},
pane_size::Size,
};

#[derive(Clone, Debug)]
pub enum PluginInstruction {
Load(RunPlugin, usize, ClientId, Size), // plugin metadata, tab_index, client_ids
Update(Option<u32>, Option<ClientId>, Event), // Focused plugin / broadcast, client_id, event data
Unload(u32), // plugin_id
Resize(u32, usize, usize), // plugin_id, columns, rows
AddClient(ClientId),
RemoveClient(ClientId),
NewTab(
Option<TerminalAction>,
Option<PaneLayout>,
Option<String>, // tab name
usize, // tab_index
ClientId,
),
Exit,
}

impl From<&PluginInstruction> for PluginContext {
fn from(plugin_instruction: &PluginInstruction) -> Self {
match *plugin_instruction {
PluginInstruction::Load(..) => PluginContext::Load,
PluginInstruction::Update(..) => PluginContext::Update,
PluginInstruction::Unload(..) => PluginContext::Unload,
PluginInstruction::Resize(..) => PluginContext::Resize,
PluginInstruction::Exit => PluginContext::Exit,
PluginInstruction::AddClient(_) => PluginContext::AddClient,
PluginInstruction::RemoveClient(_) => PluginContext::RemoveClient,
PluginInstruction::NewTab(..) => PluginContext::NewTab,
}
}
}

pub(crate) fn plugin_thread_main(
bus: Bus<PluginInstruction>,
store: Store,
data_dir: PathBuf,
plugins: PluginsConfig,
layout: Box<Layout>,
) -> Result<()> {
info!("Wasm main thread starts");

let plugin_dir = data_dir.join("plugins/");
let plugin_global_data_dir = plugin_dir.join("data");

let mut wasm_bridge = WasmBridge::new(plugins, bus.senders.clone(), store, plugin_dir);

loop {
let (event, mut err_ctx) = bus.recv().expect("failed to receive event on channel");
err_ctx.add_call(ContextType::Plugin((&event).into()));
match event {
// TODO: remove pid_tx from here
PluginInstruction::Load(run, tab_index, client_id, size) => {
wasm_bridge.load_plugin(&run, tab_index, size, client_id)?;
},
PluginInstruction::Update(pid, cid, event) => {
wasm_bridge.update_plugins(pid, cid, event)?;
},
PluginInstruction::Unload(pid) => {
wasm_bridge.unload_plugin(pid)?;
},
PluginInstruction::Resize(pid, new_columns, new_rows) => {
wasm_bridge.resize_plugin(pid, new_columns, new_rows)?;
},
PluginInstruction::AddClient(client_id) => {
wasm_bridge.add_client(client_id)?;
},
PluginInstruction::RemoveClient(client_id) => {
wasm_bridge.remove_client(client_id);
},
PluginInstruction::NewTab(
terminal_action,
tab_layout,
tab_name,
tab_index,
client_id,
) => {
let mut plugin_ids: HashMap<RunPluginLocation, Vec<u32>> = HashMap::new();
let extracted_run_instructions = tab_layout
.clone()
.unwrap_or_else(|| layout.new_tab())
.extract_run_instructions();
let size = Size::default(); // TODO: is this bad?
for run_instruction in extracted_run_instructions {
if let Some(Run::Plugin(run)) = run_instruction {
let plugin_id =
wasm_bridge.load_plugin(&run, tab_index, size, client_id)?;
plugin_ids.entry(run.location).or_default().push(plugin_id);
}
}
drop(bus.senders.send_to_pty(PtyInstruction::NewTab(
terminal_action,
tab_layout,
tab_name,
tab_index,
plugin_ids,
client_id,
)));
},
PluginInstruction::Exit => break,
}
}
info!("wasm main thread exits");

fs::remove_dir_all(&plugin_global_data_dir)
.or_else(|err| {
if err.kind() == std::io::ErrorKind::NotFound {
// I don't care...
Ok(())
} else {
Err(err)
}
})
.context("failed to cleanup plugin data directory")
}
Loading

0 comments on commit b7adfcc

Please sign in to comment.