feat(init): supervise servers+session progs: restart on death, same endpoint, backoff 0/1/5/30s then give up, restarts_clients cascade; release grants/spawn at stop (stale-slot safe); storage death fatal; init output via printer thread (never blocks on log); terminal Ctrl+C via CONTROL-badged copy, latest wins; flaky test server + spawntest restart/backoff check
This commit is contained in:
@@ -247,20 +247,15 @@ impl<C: Console> Server for TerminalServer<C> {
|
||||
self.console.flush();
|
||||
[0; 4]
|
||||
}
|
||||
types::terminal::ON_INTERRUPT => match (cap, self.on_interrupt) {
|
||||
(Some(n), None) => {
|
||||
self.on_interrupt = Some(n);
|
||||
types::terminal::ON_INTERRUPT => match cap {
|
||||
Some(n) if badge & types::terminal::CONTROL != 0 => {
|
||||
if let Some(old) = self.on_interrupt.replace(n) {
|
||||
self.console.forget(old);
|
||||
}
|
||||
[0; 4]
|
||||
}
|
||||
_ => [MALFORMED, 0, 0, 0],
|
||||
},
|
||||
types::terminal::SIGNED_OUT if badge == 0 => {
|
||||
if let Some(n) = self.on_interrupt.take() {
|
||||
self.console.forget(n);
|
||||
}
|
||||
[0; 4]
|
||||
}
|
||||
types::terminal::SIGNED_OUT => [MALFORMED, 0, 0, 0],
|
||||
types::terminal::CLEAR => {
|
||||
self.handle(Request::Clear);
|
||||
[0; 4]
|
||||
|
||||
@@ -105,8 +105,9 @@ fn line_of(t: &mut TerminalServer<Fake>) -> Vec<u8> {
|
||||
line
|
||||
}
|
||||
|
||||
/// Registered through the shell's control copy.
|
||||
fn on_interrupt(t: &mut TerminalServer<Fake>, slot: u8) -> usize {
|
||||
t.handle_call(1, [types::terminal::ON_INTERRUPT, 0, 0, 0], CapSlot::new(slot)).0[0]
|
||||
t.handle_call(1 | types::terminal::CONTROL, [types::terminal::ON_INTERRUPT, 0, 0, 0], CapSlot::new(slot)).0[0]
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -119,16 +120,6 @@ fn ctrl_c_while_a_program_runs_interrupts_it() {
|
||||
assert_eq!(&t.grid().row(0)[..2], b"^C");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn only_the_first_interrupt_notification_is_taken() {
|
||||
let mut t = term(&[]);
|
||||
assert_eq!(on_interrupt(&mut t, 7), 0);
|
||||
assert_ne!(on_interrupt(&mut t, 8), 0);
|
||||
t.console_mut_for_test().typed = vec![CTRL_C];
|
||||
t.signal(KEYS_BIT);
|
||||
assert_eq!(t.console().interrupted, [CapSlot::new(7).unwrap()]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keys_typed_ahead_start_the_next_line() {
|
||||
let mut t = term(b"s\n");
|
||||
@@ -192,15 +183,16 @@ fn a_secret_line_shows_stars_and_is_forgotten() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn only_init_lets_the_next_session_register_for_ctrl_c() {
|
||||
fn only_the_control_copy_takes_ctrl_c_and_the_latest_counts() {
|
||||
use server_framework::MALFORMED;
|
||||
let mut t = term(&[]);
|
||||
let plain = |t: &mut TerminalServer<Fake>, slot| t.handle_call(1, [types::terminal::ON_INTERRUPT, 0, 0, 0], CapSlot::new(slot)).0[0];
|
||||
assert_eq!(plain(&mut t, 6), MALFORMED, "an app, with the plain copy, cannot take it");
|
||||
assert_eq!(on_interrupt(&mut t, 7), 0);
|
||||
assert_eq!(on_interrupt(&mut t, 8), MALFORMED, "an app cannot take Ctrl+C over");
|
||||
let signed_out = |t: &mut TerminalServer<Fake>, badge| t.handle_call(badge, [types::terminal::SIGNED_OUT, 0, 0, 0], None).0[0];
|
||||
assert_eq!(signed_out(&mut t, 1), MALFORMED, "nor say the user signed out");
|
||||
assert_eq!(on_interrupt(&mut t, 8), MALFORMED);
|
||||
assert_eq!(signed_out(&mut t, 0), 0);
|
||||
assert_eq!(plain(&mut t, 8), MALFORMED, "nor take it over");
|
||||
assert_eq!(on_interrupt(&mut t, 9), 0, "a restarted shell registers again");
|
||||
assert_eq!(t.console().forgotten, [CapSlot::new(7).unwrap()]);
|
||||
assert_eq!(on_interrupt(&mut t, 9), 0, "the next shell may");
|
||||
t.console_mut_for_test().typed = vec![CTRL_C];
|
||||
t.signal(KEYS_BIT);
|
||||
assert_eq!(t.console().interrupted, [CapSlot::new(9).unwrap()]);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user