Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions libshpool/src/daemon/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -977,8 +977,6 @@ impl Server {
(None, Some(config::SessionRestoreMode::Lines(l))) => *l as usize,
(None, _) => DEFAULT_OUTPUT_SPOOL_LINES,
},
session_restore_mode:
self.config.get().session_restore_mode.clone().unwrap_or_default(),
client_connection: client_connection_rx,
client_connection_ack: client_connection_ack_tx,
tty_size_change: tty_size_change_rx,
Expand Down
12 changes: 3 additions & 9 deletions libshpool/src/daemon/shell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,6 @@ pub struct ShellToClientArgs {
pub conn_id: usize,
pub tty_size: TtySize,
pub scrollback_lines: usize,
pub session_restore_mode: config::SessionRestoreMode,
pub client_connection: crossbeam_channel::Receiver<ClientConnectionMsg>,
pub client_connection_ack: crossbeam_channel::Sender<ClientConnectionStatus>,
pub tty_size_change: crossbeam_channel::Receiver<TtySize>,
Expand Down Expand Up @@ -242,13 +241,8 @@ impl SessionInner {
let closure = move || {
let _s = span!(Level::INFO, "shell->client", s = name, cid = args.conn_id).entered();

let mut output_spool = session_restore::new(
config,
// TODO: #173 - fetch session restore mode from config dynamically
&args.session_restore_mode,
&args.tty_size,
args.scrollback_lines,
);
let mut output_spool =
session_restore::new(config, &args.tty_size, args.scrollback_lines);
let mut buf: Vec<u8> = vec![0; consts::BUF_SIZE];
let mut poll_fds = [poll::PollFd::new(
watchable_master.borrow_fd().ok_or(anyhow!("no master fd"))?,
Expand Down Expand Up @@ -432,7 +426,7 @@ impl SessionInner {
}

if do_reattach {
info!("executing reattach protocol (mode={:?})", &args.session_restore_mode);
info!("executing reattach protocol");
let restore_buf = output_spool.restore_buffer();
if let (true, ClientConnectionMsg::New(conn)) =
(!restore_buf.is_empty(), &mut client_conn)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ impl SessionSpool for NullSpool {
fn resize(&mut self, _: TtySize) {}

fn restore_buffer(&self) -> Vec<u8> {
info!("generating null restore buf");
vec![]
}

Expand Down Expand Up @@ -121,10 +122,10 @@ impl SessionSpool for Vt100Lines {
/// Creates a spool given a `mode`.
pub fn new(
config: config::Manager,
mode: &SessionRestoreMode,
size: &TtySize,
scrollback_lines: usize,
) -> Box<dyn SessionSpool + 'static> {
let mode = config.get().session_restore_mode.clone().unwrap_or_default();
let vterm_width = config.vterm_width();
match mode {
SessionRestoreMode::Simple => Box::new(NullSpool),
Expand All @@ -134,7 +135,7 @@ pub fn new(
}),
SessionRestoreMode::Lines(nlines) => Box::new(Vt100Lines {
parser: shpool_vt100::Parser::new(size.rows, vterm_width, scrollback_lines),
nlines: *nlines,
nlines,
config,
}),
}
Expand Down
69 changes: 69 additions & 0 deletions shpool/tests/attach.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1621,3 +1621,72 @@ fn up_arrow_no_crash() -> anyhow::Result<()> {

Ok(())
}

#[test]
#[timeout(30000)]
#[cfg_attr(target_os = "macos", ignore)]
fn dynamic_session_restore_mode() -> anyhow::Result<()> {
let tmp_dir = tmpdir::Dir::new("/tmp/shpool-test")?;
let config_tmpl = fs::read_to_string(support::testdata_file("dynamic_restore.toml.tmpl"))?;
let config_file = tmp_dir.path().join("shpool.toml");

// Start with "simple" mode
let config_contents = config_tmpl.replace("REPLACE_ME", "\"simple\"");
fs::write(&config_file, &config_contents)?;

let mut daemon_proc = support::daemon::Proc::new(&config_file, DaemonArgs::default())
.context("starting daemon proc")?;

// Register all expected events up front.
let mut waiter = daemon_proc.events.take().unwrap().waiter([
"daemon-bidi-stream-done", // s1 detach
"daemon-reload-config", // config reload
"daemon-bidi-stream-done", // s2 detach
]);

// Create session s1
{
let mut a1 = daemon_proc.attach("s1", Default::default()).context("starting s1")?;
let mut lm1 = a1.line_matcher()?;
a1.run_cmd("echo foo")?;
lm1.scan_until_re("foo$")?;
} // detach s1
waiter.wait_event("daemon-bidi-stream-done")?;

// Change config to { lines = 2 }
let config_contents = config_tmpl.replace("REPLACE_ME", "{ lines = 2 }");
fs::write(&config_file, config_contents)?;

waiter.wait_event("daemon-reload-config")?;

// Create session s2
{
let mut a2 = daemon_proc.attach("s2", Default::default()).context("starting s2")?;
let mut lm2 = a2.line_matcher()?;
a2.run_cmd("echo bar")?;
lm2.scan_until_re("bar$")?;
} // detach s2
daemon_proc.events = Some(waiter.wait_final_event("daemon-bidi-stream-done")?);

// Verify s1 still has "simple" behavior (no restore)
{
let mut a1 = daemon_proc.attach("s1", Default::default()).context("reattaching s1")?;
let mut lm1 = a1.line_matcher()?;
lm1.never_matches("foo$")?;

a1.run_cmd("echo s1_alive")?;
lm1.scan_until_re("s1_alive$")?;

a1.proc.kill()?;
}

// Verify s2 has "lines = 2" behavior (restores bar)
{
let mut a2 = daemon_proc.attach("s2", Default::default()).context("reattaching s2")?;
let mut lm2 = a2.line_matcher()?;
// It SHOULD see "bar" again on re-attach
lm2.scan_until_re("bar$")?;
}

Ok(())
}
9 changes: 9 additions & 0 deletions shpool/tests/data/dynamic_restore.toml.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
norc = true
noecho = true
shell = "/bin/bash"
session_restore_mode = REPLACE_ME
prompt_prefix = ""

[env]
PS1 = "prompt> "
TERM = ""
Loading