diff --git a/backend/src/manager/mod.rs b/backend/src/manager/mod.rs index cee63477b..ee7a23932 100644 --- a/backend/src/manager/mod.rs +++ b/backend/src/manager/mod.rs @@ -16,10 +16,10 @@ use nix::sys::signal::Signal; use num_enum::TryFromPrimitive; use patch_db::DbHandle; use sqlx::{Executor, Postgres}; +use tokio::sync::mpsc::UnboundedSender; use tokio::sync::watch::error::RecvError; use tokio::sync::watch::{channel, Receiver, Sender}; use tokio::sync::{Mutex, Notify, RwLock}; -use tokio::{sync::mpsc::UnboundedSender, task::JoinHandle}; use tokio_stream::wrappers::UnboundedReceiverStream; use torut::onion::TorSecretKeyV3; use tracing::instrument; @@ -196,15 +196,10 @@ async fn run_main( persistant.wait_for_persistant().await; let is_injectable_main = check_is_injectable_main(state); - let mut runtime = match injectable_main(state) { - InjectableMain::None => { - tokio::spawn(async move { start_up_image(rt_state, generated_certificate).await }) - } - #[cfg(feature = "js_engine")] - InjectableMain::Script(_) => { - tokio::spawn(async move { start_up_image(rt_state, generated_certificate).await }) - } - }; + let mut runtime = NonDetachingJoinHandle::from(tokio::spawn(start_up_image( + rt_state, + generated_certificate, + ))); let ip = match is_injectable_main { false => Some(match get_running_ip(state, &mut runtime).await { GetRunninIp::Ip(x) => x, @@ -276,16 +271,16 @@ impl Manager { let thread_shared = shared.clone(); let persistant_container = PersistantContainer::new(&thread_shared); let managers_persistant = persistant_container.clone(); - let thread = tokio::spawn(async move { + let thread = NonDetachingJoinHandle::from(tokio::spawn(async move { tokio::select! { _ = manager_thread_loop(recv, &thread_shared, managers_persistant.clone()) => (), _ = synchronizer(&*thread_shared, managers_persistant) => (), } - }); + })); Ok(Manager { shared, persistant_container, - thread: Container::new(Some(thread.into())), + thread: Container::new(Some(thread)), }) } @@ -736,7 +731,7 @@ impl PersistantContainer { } } None => { - return Err("Couldn't get a command inserter in current service".to_string()) + return Err("Expecting containers.main in the package manifest".to_string()) } }; Ok::(id) @@ -937,7 +932,7 @@ enum GetRunninIp { EarlyExit(Result), } -type RuntimeOfCommand = JoinHandle, Error>>; +type RuntimeOfCommand = NonDetachingJoinHandle, Error>>; async fn get_running_ip( state: &Arc, diff --git a/backend/src/procedure/docker.rs b/backend/src/procedure/docker.rs index 663ebb7c0..746247bfc 100644 --- a/backend/src/procedure/docker.rs +++ b/backend/src/procedure/docker.rs @@ -81,6 +81,8 @@ pub struct DockerProcedure { #[serde(default)] pub args: Vec, #[serde(default)] + pub inject: bool, + #[serde(default)] pub mounts: BTreeMap, #[serde(default)] pub io_format: Option, @@ -113,6 +115,7 @@ impl DockerProcedure { system: injectable.system, entrypoint: injectable.entrypoint.clone(), args: injectable.args.clone(), + inject: false, mounts: container.mounts.clone(), io_format: injectable.io_format, sigterm_timeout: injectable.sigterm_timeout, @@ -129,6 +132,7 @@ impl DockerProcedure { system: container.system, entrypoint: "sleep".to_string(), args: Vec::new(), + inject: false, mounts: container.mounts.clone(), io_format: None, sigterm_timeout: container.sigterm_timeout, @@ -184,7 +188,8 @@ impl DockerProcedure { .arg("--name") .arg(&container_name) .arg(format!("--hostname={}", &container_name)) - .arg("--no-healthcheck"); + .arg("--no-healthcheck") + .kill_on_drop(true); match ctx .docker .remove_container( @@ -796,7 +801,6 @@ impl LongRunning { pkg_id: &PackageId, pkg_version: &Version, ) -> Result { - tracing::error!("BLUJ setup_long_running_docker_cmd {container_name}"); const INIT_EXEC: &str = "/start9/embassy_container_init"; const BIND_LOCATION: &str = "/usr/lib/embassy/container"; tracing::trace!("setup_long_running_docker_cmd"); @@ -831,7 +835,8 @@ impl LongRunning { .arg("--entrypoint") .arg(format!("{INIT_EXEC}.{image_architecture}")) .arg("-i") - .arg("--rm"); + .arg("--rm") + .kill_on_drop(true); for (volume_id, dst) in &docker.mounts { let volume = if let Some(v) = volumes.get(volume_id) { diff --git a/backend/src/procedure/mod.rs b/backend/src/procedure/mod.rs index 1cee646fc..b8a73830c 100644 --- a/backend/src/procedure/mod.rs +++ b/backend/src/procedure/mod.rs @@ -70,6 +70,11 @@ impl PackageProcedure { ) -> Result, Error> { tracing::trace!("Procedure execute {} {} - {:?}", self, pkg_id, name); match self { + PackageProcedure::Docker(procedure) if procedure.inject == true => { + procedure + .inject(ctx, pkg_id, pkg_version, name, volumes, input, timeout) + .await + } PackageProcedure::Docker(procedure) => { procedure .execute(ctx, pkg_id, pkg_version, name, volumes, input, timeout) diff --git a/backend/src/s9pk/reader.rs b/backend/src/s9pk/reader.rs index b6dcd3dda..eefc4ae63 100644 --- a/backend/src/s9pk/reader.rs +++ b/backend/src/s9pk/reader.rs @@ -230,6 +230,15 @@ impl S9pkReader { &man.volumes, &validated_image_ids, )?; + + if man.containers.is_some() + && matches!(man.main, crate::procedure::PackageProcedure::Docker(_)) + { + return Err(Error::new( + eyre!("Cannot have a main docker and a main in containers"), + crate::ErrorKind::ValidateS9pk, + )); + } if let Some(props) = &man.properties { props .validate(