mod record_writer;
mod relay;
mod shared;
mod startup;
use std::path::PathBuf;
use ohno::AppError;
use crate::constants::CONNECT_TIMEOUT;
use crate::pal::processes::Processes;
use crate::pal::pseudoconsole::Pseudoconsole;
use crate::pal::session_store::SessionStore;
use crate::pal::transport::Transport;
use crate::protocol::Message;
use crate::supervisor::relay::serve;
use crate::supervisor::startup::{FailedStartup, InitGuard, initialize};
use crate::{AppCommand, StartupFailedError};
pub(crate) struct SessionSpec {
pub launch_directory: PathBuf,
pub command: AppCommand,
pub started_at_unix_ms: u64,
}
#[cfg_attr(test, mutants::skip)]
pub(crate) fn run_supervisor<P, S, T, C>(
processes: &P,
store: &S,
transport: &T,
pty_host: &C,
startup_pipe: &str,
spec: SessionSpec,
) -> Result<i32, AppError>
where
P: Processes,
S: SessionStore + Clone,
T: Transport + Clone + Send + Sync + 'static,
C: Pseudoconsole + Clone + Send + Sync + 'static,
{
let startup = transport
.connect(startup_pipe, CONNECT_TIMEOUT)
.map_err(StartupFailedError::caused_by)?;
let mut guard = InitGuard {
processes,
store,
transport,
pty_host,
job: None,
pty: None,
listener: None,
session: None,
committed: false,
};
let result = initialize(&mut guard, processes, store, transport, pty_host, spec);
let initialized = match result {
Ok(initialized) => initialized,
Err(FailedStartup { step, error }) => {
_ = transport.send(startup, &Message::StartupErr { step });
transport.disconnect(startup);
return Err(error);
}
};
let startup_ok = Message::StartupOk {
session_id: initialized.session_id,
launcher_tie: processes.launcher_tie(),
pipe_name: initialized.pipe_name.clone(),
};
if transport.send(startup, &startup_ok).is_err() {
transport.disconnect(startup);
return Err(StartupFailedError::new().into());
}
let committed = transport.recv_timeout(startup, CONNECT_TIMEOUT);
if !matches!(committed, Ok(Message::StartupCommit)) {
transport.disconnect(startup);
return Err(StartupFailedError::new().into());
}
guard.committed = true;
let status = serve(processes, store, transport, pty_host, &initialized, startup)?;
Ok(status)
}
#[cfg(test)]
#[cfg_attr(coverage_nightly, coverage(off))]
mod tests;