aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKunal Mohan <44079328+kunalmohan@users.noreply.github.com>2020-12-09 22:31:26 +0530
committerGitHub <noreply@github.com>2020-12-09 18:01:26 +0100
commit92d1bcff4c0d1d886cefee6984d5533c5ea8dd6f (patch)
tree2ef85153a55e61f1d97e03dfa608ac853fe22887 /src
parentfix(style): else-if ladder -> match (#86) (diff)
downloadsl0ppij-92d1bcff4c0d1d886cefee6984d5533c5ea8dd6f.tar.gz
sl0ppij-92d1bcff4c0d1d886cefee6984d5533c5ea8dd6f.tar.xz
sl0ppij-92d1bcff4c0d1d886cefee6984d5533c5ea8dd6f.zip
feat(infrastructure): introduce ErrorContext for tracking errors across threads (#83)
* Implement ErrorContext for tracking errors across threads * reorder Instruction and ErrorContext * Add ContextType, AppContext, ScreenContext, PtyContext * Use ArrayVec in ErrorContext * increase MAX_THREAD_CALL_STACK to 6 * Custom implement Debug for ErrorContext ad ContextType and color output * Use os_input instead of println!() * Use array instead of ArrayVec and some cleanup * Introduce SenderWithContext * Keep arrayvec at v0.5.1
Diffstat (limited to 'src')
-rw-r--r--src/errors.rs192
-rw-r--r--src/input.rs28
-rw-r--r--src/main.rs90
-rw-r--r--src/pty_bus.rs22
-rw-r--r--src/screen.rs18
-rw-r--r--src/utils/logging.rs2
6 files changed, 299 insertions, 53 deletions
diff --git a/src/errors.rs b/src/errors.rs
index 437db0dd..8478969d 100644
--- a/src/errors.rs
+++ b/src/errors.rs
@@ -1,10 +1,17 @@
-use crate::AppInstruction;
+use crate::pty_bus::PtyInstruction;
+use crate::screen::ScreenInstruction;
+use crate::{AppInstruction, SenderWithContext, OPENCALLS};
use backtrace::Backtrace;
+use std::fmt::{Display, Error, Formatter};
use std::panic::PanicInfo;
-use std::sync::mpsc::SyncSender;
use std::{process, thread};
-pub fn handle_panic(info: &PanicInfo<'_>, send_app_instructions: &SyncSender<AppInstruction>) {
+const MAX_THREAD_CALL_STACK: usize = 6;
+
+pub fn handle_panic(
+ info: &PanicInfo<'_>,
+ send_app_instructions: &SenderWithContext<AppInstruction>,
+) {
let backtrace = Backtrace::new();
let thread = thread::current();
let thread = thread.name().unwrap_or("unnamed");
@@ -14,9 +21,12 @@ pub fn handle_panic(info: &PanicInfo<'_>, send_app_instructions: &SyncSender<App
None => info.payload().downcast_ref::<String>().map(|s| &**s),
};
+ let err_ctx = OPENCALLS.with(|ctx| *ctx.borrow());
+
let backtrace = match (info.location(), msg) {
(Some(location), Some(msg)) => format!(
- "\nthread '{}' panicked at '{}': {}:{}\n{:?}",
+ "{}\n\u{1b}[0;0mError: \u{1b}[0;31mthread '{}' panicked at '{}': {}:{}\n\u{1b}[0;0m{:?}",
+ err_ctx,
thread,
msg,
location.file(),
@@ -24,17 +34,21 @@ pub fn handle_panic(info: &PanicInfo<'_>, send_app_instructions: &SyncSender<App
backtrace
),
(Some(location), None) => format!(
- "\nthread '{}' panicked: {}:{}\n{:?}",
+ "{}\n\u{1b}[0;0mError: \u{1b}[0;31mthread '{}' panicked: {}:{}\n\u{1b}[0;0m{:?}",
+ err_ctx,
thread,
location.file(),
location.line(),
backtrace
),
(None, Some(msg)) => format!(
- "\nthread '{}' panicked at '{}'\n{:?}",
- thread, msg, backtrace
+ "{}\n\u{1b}[0;0mError: \u{1b}[0;31mthread '{}' panicked at '{}'\n\u{1b}[0;0m{:?}",
+ err_ctx, thread, msg, backtrace
+ ),
+ (None, None) => format!(
+ "{}\n\u{1b}[0;0mError: \u{1b}[0;31mthread '{}' panicked\n\u{1b}[0;0m{:?}",
+ err_ctx, thread, backtrace
),
- (None, None) => format!("\nthread '{}' panicked\n{:?}", thread, backtrace),
};
if thread == "main" {
@@ -46,3 +60,165 @@ pub fn handle_panic(info: &PanicInfo<'_>, send_app_instructions: &SyncSender<App
.unwrap();
}
}
+
+#[derive(Clone, Copy)]
+pub struct ErrorContext {
+ calls: [ContextType; MAX_THREAD_CALL_STACK],
+}
+
+impl ErrorContext {
+ pub fn new() -> Self {
+ Self {
+ calls: [ContextType::Empty; MAX_THREAD_CALL_STACK],
+ }
+ }
+
+ pub fn add_call(&mut self, call: ContextType) {
+ for ctx in self.calls.iter_mut() {
+ if *ctx == ContextType::Empty {
+ *ctx = call;
+ break;
+ }
+ }
+ OPENCALLS.with(|ctx| *ctx.borrow_mut() = *self);
+ }
+}
+
+impl Display for ErrorContext {
+ fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
+ writeln!(f, "Originating Thread(s):")?;
+ for (index, ctx) in self.calls.iter().enumerate() {
+ if *ctx == ContextType::Empty {
+ break;
+ }
+ writeln!(f, "\u{1b}[0;0m{}. {}", index + 1, ctx)?;
+ }
+ Ok(())
+ }
+}
+
+#[derive(Copy, Clone, PartialEq)]
+pub enum ContextType {
+ Screen(ScreenContext),
+ Pty(PtyContext),
+ App(AppContext),
+ IPCServer,
+ StdinHandler,
+ AsyncTask,
+ Empty,
+}
+
+impl Display for ContextType {
+ fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
+ let purple = "\u{1b}[1;35m";
+ let green = "\u{1b}[0;32m";
+ match *self {
+ ContextType::Screen(c) => write!(f, "{}screen_thread: {}{:?}", purple, green, c),
+ ContextType::Pty(c) => write!(f, "{}pty_thread: {}{:?}", purple, green, c),
+ ContextType::App(c) => write!(f, "{}main_thread: {}{:?}", purple, green, c),
+ ContextType::IPCServer => write!(f, "{}ipc_server: {}AcceptInput", purple, green),
+ ContextType::StdinHandler => {
+ write!(f, "{}stdin_handler_thread: {}AcceptInput", purple, green)
+ }
+ ContextType::AsyncTask => {
+ write!(f, "{}stream_terminal_bytes: {}AsyncTask", purple, green)
+ }
+ ContextType::Empty => write!(f, ""),
+ }
+ }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq)]
+pub enum ScreenContext {
+ HandlePtyEvent,
+ Render,
+ NewPane,
+ HorizontalSplit,
+ VerticalSplit,
+ WriteCharacter,
+ ResizeLeft,
+ ResizeRight,
+ ResizeDown,
+ ResizeUp,
+ MoveFocus,
+ MoveFocusLeft,
+ MoveFocusDown,
+ MoveFocusUp,
+ MoveFocusRight,
+ Quit,
+ ScrollUp,
+ ScrollDown,
+ ClearScroll,
+ CloseFocusedPane,
+ ToggleActiveTerminalFullscreen,
+ ClosePane,
+ ApplyLayout,
+}
+
+impl From<&ScreenInstruction> for ScreenContext {
+ fn from(screen_instruction: &ScreenInstruction) -> Self {
+ match *screen_instruction {
+ ScreenInstruction::Pty(..) => ScreenContext::HandlePtyEvent,
+ ScreenInstruction::Render => ScreenContext::Render,
+ ScreenInstruction::NewPane(_) => ScreenContext::NewPane,
+ ScreenInstruction::HorizontalSplit(_) => ScreenContext::HorizontalSplit,
+ ScreenInstruction::VerticalSplit(_) => ScreenContext::VerticalSplit,
+ ScreenInstruction::WriteCharacter(_) => ScreenContext::WriteCharacter,
+ ScreenInstruction::ResizeLeft => ScreenContext::ResizeLeft,
+ ScreenInstruction::ResizeRight => ScreenContext::ResizeRight,
+ ScreenInstruction::ResizeDown => ScreenContext::ResizeDown,
+ ScreenInstruction::ResizeUp => ScreenContext::ResizeUp,
+ ScreenInstruction::MoveFocus => ScreenContext::MoveFocus,
+ ScreenInstruction::MoveFocusLeft => ScreenContext::MoveFocusLeft,
+ ScreenInstruction::MoveFocusDown => ScreenContext::MoveFocusDown,
+ ScreenInstruction::MoveFocusUp => ScreenContext::MoveFocusUp,
+ ScreenInstruction::MoveFocusRight => ScreenContext::MoveFocusRight,
+ ScreenInstruction::Quit => ScreenContext::Quit,
+ ScreenInstruction::ScrollUp => ScreenContext::ScrollUp,
+ ScreenInstruction::ScrollDown => ScreenContext::ScrollDown,
+ ScreenInstruction::ClearScroll => ScreenContext::ClearScroll,
+ ScreenInstruction::CloseFocusedPane => ScreenContext::CloseFocusedPane,
+ ScreenInstruction::ToggleActiveTerminalFullscreen => {
+ ScreenContext::ToggleActiveTerminalFullscreen
+ }
+ ScreenInstruction::ClosePane(_) => ScreenContext::ClosePane,
+ ScreenInstruction::ApplyLayout(_) => ScreenContext::ApplyLayout,
+ }
+ }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq)]
+pub enum PtyContext {
+ SpawnTerminal,
+ SpawnTerminalVertically,
+ SpawnTerminalHorizontally,
+ ClosePane,
+ Quit,
+}
+
+impl From<&PtyInstruction> for PtyContext {
+ fn from(pty_instruction: &PtyInstruction) -> Self {
+ match *pty_instruction {
+ PtyInstruction::SpawnTerminal(_) => PtyContext::SpawnTerminal,
+ PtyInstruction::SpawnTerminalVertically(_) => PtyContext::SpawnTerminalVertically,
+ PtyInstruction::SpawnTerminalHorizontally(_) => PtyContext::SpawnTerminalHorizontally,
+ PtyInstruction::ClosePane(_) => PtyContext::ClosePane,
+ PtyInstruction::Quit => PtyContext::Quit,
+ }
+ }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq)]
+pub enum AppContext {
+ Exit,
+ Error,
+}
+
+impl From<&AppInstruction> for AppContext {
+ fn from(app_instruction: &AppInstruction) -> Self {
+ match *app_instruction {
+ AppInstruction::Exit => AppContext::Exit,
+ AppInstruction::Error(_) => AppContext::Error,
+ }
+ }
+}
diff --git a/src/input.rs b/src/input.rs
index ea2c4d41..6d82f4f9 100644
--- a/src/input.rs
+++ b/src/input.rs
@@ -1,28 +1,27 @@
/// Module for handling input
-use std::sync::mpsc::{Sender, SyncSender};
-
+use crate::errors::ContextType;
use crate::os_input_output::OsApi;
use crate::pty_bus::PtyInstruction;
use crate::screen::ScreenInstruction;
-use crate::AppInstruction;
use crate::CommandIsExecuting;
+use crate::{AppInstruction, SenderWithContext, OPENCALLS};
struct InputHandler {
mode: InputMode,
os_input: Box<dyn OsApi>,
command_is_executing: CommandIsExecuting,
- send_screen_instructions: Sender<ScreenInstruction>,
- send_pty_instructions: Sender<PtyInstruction>,
- send_app_instructions: SyncSender<AppInstruction>,
+ send_screen_instructions: SenderWithContext<ScreenInstruction>,
+ send_pty_instructions: SenderWithContext<PtyInstruction>,
+ send_app_instructions: SenderWithContext<AppInstruction>,
}
impl InputHandler {
fn new(
os_input: Box<dyn OsApi>,
command_is_executing: CommandIsExecuting,
- send_screen_instructions: Sender<ScreenInstruction>,
- send_pty_instructions: Sender<PtyInstruction>,
- send_app_instructions: SyncSender<AppInstruction>,
+ send_screen_instructions: SenderWithContext<ScreenInstruction>,
+ send_pty_instructions: SenderWithContext<PtyInstruction>,
+ send_app_instructions: SenderWithContext<AppInstruction>,
) -> Self {
InputHandler {
mode: InputMode::Normal,
@@ -36,6 +35,11 @@ impl InputHandler {
/// Main event loop
fn get_input(&mut self) {
+ let mut err_ctx = OPENCALLS.with(|ctx| *ctx.borrow());
+ err_ctx.add_call(ContextType::StdinHandler);
+ self.send_pty_instructions.update(err_ctx);
+ self.send_app_instructions.update(err_ctx);
+ self.send_screen_instructions.update(err_ctx);
loop {
match self.mode {
InputMode::Normal => self.read_normal_mode(),
@@ -263,9 +267,9 @@ pub enum InputMode {
pub fn input_loop(
os_input: Box<dyn OsApi>,
command_is_executing: CommandIsExecuting,
- send_screen_instructions: Sender<ScreenInstruction>,
- send_pty_instructions: Sender<PtyInstruction>,
- send_app_instructions: SyncSender<AppInstruction>,
+ send_screen_instructions: SenderWithContext<ScreenInstruction>,
+ send_pty_instructions: SenderWithContext<PtyInstruction>,
+ send_app_instructions: SenderWithContext<AppInstruction>,
) {
let _handler = InputHandler::new(
os_input,
diff --git a/src/main.rs b/src/main.rs
index 0ad09ed0..27deb093 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -15,13 +15,14 @@ mod utils;
use std::io::Write;
use std::os::unix::net::UnixStream;
use std::path::PathBuf;
-use std::sync::mpsc::{channel, sync_channel, Receiver, Sender, SyncSender};
+use std::sync::mpsc::{channel, sync_channel, Receiver, SendError, Sender, SyncSender};
use std::thread;
use serde::{Deserialize, Serialize};
use structopt::StructOpt;
use crate::command_is_executing::CommandIsExecuting;
+use crate::errors::{AppContext, ContextType, ErrorContext, PtyContext, ScreenContext};
use crate::input::input_loop;
use crate::layout::Layout;
use crate::os_input_output::{get_os_input, OsApi};
@@ -31,6 +32,9 @@ use crate::utils::{
consts::{MOSAIC_IPC_PIPE, MOSAIC_TMP_DIR, MOSAIC_TMP_LOG_DIR},
logging::*,
};
+use std::cell::RefCell;
+
+thread_local!(static OPENCALLS: RefCell<ErrorContext> = RefCell::new(ErrorContext::new()));
#[derive(Serialize, Deserialize, Debug)]
enum ApiCommand {
@@ -40,6 +44,38 @@ enum ApiCommand {
MoveFocus,
}
+#[derive(Clone)]
+enum SenderType<T: Clone> {
+ Sender(Sender<(T, ErrorContext)>),
+ SyncSender(SyncSender<(T, ErrorContext)>),
+}
+
+#[derive(Clone)]
+pub struct SenderWithContext<T: Clone> {
+ err_ctx: ErrorContext,
+ sender: SenderType<T>,
+}
+
+impl<T: Clone> SenderWithContext<T> {
+ fn new(err_ctx: ErrorContext, sender: SenderType<T>) -> Self {
+ Self { err_ctx, sender }
+ }
+
+ pub fn send(&self, event: T) -> Result<(), SendError<(T, ErrorContext)>> {
+ match self.sender {
+ SenderType::Sender(ref s) => s.send((event, self.err_ctx)),
+ SenderType::SyncSender(ref s) => s.send((event, self.err_ctx)),
+ }
+ }
+
+ pub fn update(&mut self, new_ctx: ErrorContext) {
+ self.err_ctx = new_ctx;
+ }
+}
+
+unsafe impl<T: Clone> Send for SenderWithContext<T> {}
+unsafe impl<T: Clone> Sync for SenderWithContext<T> {}
+
#[derive(StructOpt, Debug, Default)]
#[structopt(name = "mosaic")]
pub struct Opt {
@@ -94,6 +130,7 @@ pub fn main() {
}
}
+#[derive(Clone)]
pub enum AppInstruction {
Exit,
Error(String),
@@ -107,17 +144,24 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: Opt) {
let full_screen_ws = os_input.get_terminal_size_using_fd(0);
os_input.into_raw_mode(0);
let (send_screen_instructions, receive_screen_instructions): (
- Sender<ScreenInstruction>,
- Receiver<ScreenInstruction>,
+ Sender<(ScreenInstruction, ErrorContext)>,
+ Receiver<(ScreenInstruction, ErrorContext)>,
) = channel();
+ let err_ctx = OPENCALLS.with(|ctx| *ctx.borrow());
+ let mut send_screen_instructions =
+ SenderWithContext::new(err_ctx, SenderType::Sender(send_screen_instructions));
let (send_pty_instructions, receive_pty_instructions): (
- Sender<PtyInstruction>,
- Receiver<PtyInstruction>,
+ Sender<(PtyInstruction, ErrorContext)>,
+ Receiver<(PtyInstruction, ErrorContext)>,
) = channel();
+ let mut send_pty_instructions =
+ SenderWithContext::new(err_ctx, SenderType::Sender(send_pty_instructions));
let (send_app_instructions, receive_app_instructions): (
- SyncSender<AppInstruction>,
- Receiver<AppInstruction>,
+ SyncSender<(AppInstruction, ErrorContext)>,
+ Receiver<(AppInstruction, ErrorContext)>,
) = sync_channel(0);
+ let send_app_instructions =
+ SenderWithContext::new(err_ctx, SenderType::SyncSender(send_app_instructions));
let mut screen = Screen::new(
receive_screen_instructions,
send_pty_instructions.clone(),
@@ -156,10 +200,12 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: Opt) {
}
loop {
- let event = pty_bus
+ 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)));
+ pty_bus.send_screen_instructions.update(err_ctx);
match event {
PtyInstruction::SpawnTerminal(file_to_open) => {
pty_bus.spawn_terminal(file_to_open);
@@ -190,10 +236,13 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: Opt) {
.spawn({
let mut command_is_executing = command_is_executing.clone();
move || loop {
- let event = screen
+ let (event, mut err_ctx) = screen
.receiver
.recv()
.expect("failed to receive event on channel");
+ err_ctx.add_call(ContextType::Screen(ScreenContext::from(&event)));
+ screen.send_app_instructions.update(err_ctx);
+ screen.send_pty_instructions.update(err_ctx);
match event {
ScreenInstruction::Pty(pid, vte_event) => {
screen.handle_pty_event(pid, vte_event);
@@ -388,12 +437,16 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: Opt) {
.name("ipc_server".to_string())
.spawn({
use std::io::Read;
- let send_pty_instructions = send_pty_instructions.clone();
- let send_screen_instructions = send_screen_instructions.clone();
+ let mut send_pty_instructions = send_pty_instructions.clone();
+ let mut send_screen_instructions = send_screen_instructions.clone();
move || {
std::fs::remove_file(MOSAIC_IPC_PIPE).ok();
let listener = std::os::unix::net::UnixListener::bind(MOSAIC_IPC_PIPE)
.expect("could not listen on ipc socket");
+ let mut err_ctx = OPENCALLS.with(|ctx| *ctx.borrow());
+ err_ctx.add_call(ContextType::IPCServer);
+ send_pty_instructions.update(err_ctx);
+ send_screen_instructions.update(err_ctx);
for stream in listener.incoming() {
match stream {
@@ -456,9 +509,13 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: Opt) {
#[warn(clippy::never_loop)]
loop {
- let app_instruction = receive_app_instructions
+ let (app_instruction, mut err_ctx) = receive_app_instructions
.recv()
.expect("failed to receive app instruction on channel");
+
+ err_ctx.add_call(ContextType::App(AppContext::from(&app_instruction)));
+ send_screen_instructions.update(err_ctx);
+ send_pty_instructions.update(err_ctx);
match app_instruction {
AppInstruction::Exit => {
let _ = send_screen_instructions.send(ScreenInstruction::Quit);
@@ -466,10 +523,15 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: Opt) {
break;
}
AppInstruction::Error(backtrace) => {
- os_input.unset_raw_mode(0);
- println!("{}", backtrace);
let _ = send_screen_instructions.send(ScreenInstruction::Quit);
let _ = send_pty_instructions.send(PtyInstruction::Quit);
+ os_input.unset_raw_mode(0);
+ let goto_start_of_last_line = format!("\u{1b}[{};{}H", full_screen_ws.rows, 1);
+ let error = format!("{}\n{}", goto_start_of_last_line, backtrace);
+ let _ = os_input
+ .get_stdout_writer()
+ .write(error.as_bytes())
+ .unwrap();
for thread_handler in active_threads {
let _ = thread_handler.join();
}
diff --git a/src/pty_bus.rs b/src/pty_bus.rs
index 078e3271..758271c3 100644
--- a/src/pty_bus.rs
+++ b/src/pty_bus.rs
@@ -4,15 +4,16 @@ use ::async_std::task::*;
use ::std::collections::HashMap;
use ::std::os::unix::io::RawFd;
use ::std::pin::*;
-use ::std::sync::mpsc::{Receiver, Sender};
+use ::std::sync::mpsc::Receiver;
use ::std::time::{Duration, Instant};
use ::vte;
use std::path::PathBuf;
+use crate::errors::{ContextType, ErrorContext};
use crate::layout::Layout;
use crate::os_input_output::OsApi;
use crate::utils::logging::debug_to_file;
-use crate::ScreenInstruction;
+use crate::{ScreenInstruction, SenderWithContext, OPENCALLS};
pub struct ReadFromPid {
pid: RawFd,
@@ -75,11 +76,11 @@ pub enum VteEvent {
struct VteEventSender {
id: RawFd,
- sender: Sender<ScreenInstruction>,
+ sender: SenderWithContext<ScreenInstruction>,
}
impl VteEventSender {
- pub fn new(id: RawFd, sender: Sender<ScreenInstruction>) -> Self {
+ pub fn new(id: RawFd, sender: SenderWithContext<ScreenInstruction>) -> Self {
VteEventSender { id, sender }
}
}
@@ -151,8 +152,8 @@ pub enum PtyInstruction {
}
pub struct PtyBus {
- pub send_screen_instructions: Sender<ScreenInstruction>,
- pub receive_pty_instructions: Receiver<PtyInstruction>,
+ pub send_screen_instructions: SenderWithContext<ScreenInstruction>,
+ pub receive_pty_instructions: Receiver<(PtyInstruction, ErrorContext)>,
pub id_to_child_pid: HashMap<RawFd, RawFd>,
os_input: Box<dyn OsApi>,
debug_to_file: bool,
@@ -160,12 +161,15 @@ pub struct PtyBus {
fn stream_terminal_bytes(
pid: RawFd,
- send_screen_instructions: Sender<ScreenInstruction>,
+ mut send_screen_instructions: SenderWithContext<ScreenInstruction>,
os_input: Box<dyn OsApi>,
debug: bool,
) {
+ let mut err_ctx = OPENCALLS.with(|ctx| *ctx.borrow());
task::spawn({
async move {
+ err_ctx.add_call(ContextType::AsyncTask);
+ send_screen_instructions.update(err_ctx);
let mut vte_parser = vte::Parser::new();
let mut vte_event_sender = VteEventSender::new(pid, send_screen_instructions.clone());
let mut terminal_bytes = ReadFromPid::new(&pid, os_input);
@@ -233,8 +237,8 @@ fn stream_terminal_bytes(
impl PtyBus {
pub fn new(
- receive_pty_instructions: Receiver<PtyInstruction>,
- send_screen_instructions: Sender<ScreenInstruction>,
+ receive_pty_instructions: Receiver<(PtyInstruction, ErrorContext)>,
+ send_screen_instructions: SenderWithContext<ScreenInstruction>,
os_input: Box<dyn OsApi>,
debug_to_file: bool,
) -> Self {
diff --git a/src/screen.rs b/src/screen.rs
index e00cc0a9..79442a97 100644
--- a/src/screen.rs
+++ b/src/screen.rs
@@ -1,16 +1,16 @@
use std::collections::{BTreeMap, HashSet};
use std::io::Write;
use std::os::unix::io::RawFd;
-use std::sync::mpsc::{Receiver, Sender, SyncSender};
+use std::sync::mpsc::Receiver;
use crate::boundaries::Boundaries;
use crate::boundaries::Rect;
+use crate::errors::ErrorContext;
use crate::layout::Layout;
use crate::os_input_output::OsApi;
use crate::pty_bus::{PtyInstruction, VteEvent};
use crate::terminal_pane::{PositionAndSize, TerminalPane};
-use crate::utils::logging::debug_log_to_file;
-use crate::AppInstruction;
+use crate::{AppInstruction, SenderWithContext};
/*
* Screen
@@ -78,10 +78,10 @@ pub enum ScreenInstruction {
}
pub struct Screen {
- pub receiver: Receiver<ScreenInstruction>,
+ pub receiver: Receiver<(ScreenInstruction, ErrorContext)>,
max_panes: Option<usize>,
- send_pty_instructions: Sender<PtyInstruction>,
- send_app_instructions: SyncSender<AppInstruction>,
+ pub send_pty_instructions: SenderWithContext<PtyInstruction>,
+ pub send_app_instructions: SenderWithContext<AppInstruction>,
full_screen_ws: PositionAndSize,
terminals: BTreeMap<RawFd, TerminalPane>, // BTreeMap because we need a predictable order when changing focus
panes_to_hide: HashSet<RawFd>,
@@ -92,9 +92,9 @@ pub struct Screen {
impl Screen {
pub fn new(
- receive_screen_instructions: Receiver<ScreenInstruction>,
- send_pty_instructions: Sender<PtyInstruction>,
- send_app_instructions: SyncSender<AppInstruction>,
+ receive_screen_instructions: Receiver<(ScreenInstruction, ErrorContext)>,
+ send_pty_instructions: SenderWithContext<PtyInstruction>,
+ send_app_instructions: SenderWithContext<AppInstruction>,
full_screen_ws: &PositionAndSize,
os_api: Box<dyn OsApi>,
max_panes: Option<usize>,
diff --git a/src/utils/logging.rs b/src/utils/logging.rs
index 84a2da8f..05af455c 100644
--- a/src/utils/logging.rs
+++ b/src/utils/logging.rs
@@ -37,7 +37,7 @@ pub fn debug_log_to_file_without_newline(message: String) -> io::Result<()> {
file.write_all(message.as_bytes())
}
-pub fn debug_log_to_file_pid_3(message: String, pid: RawFd) -> io::Result<()> {
+pub fn _debug_log_to_file_pid_3(message: String, pid: RawFd) -> io::Result<()> {
if pid == 3 {
debug_log_to_file(message)
} else {