From 9b4eea2802654d613f0607d84e4cb19580149f63 Mon Sep 17 00:00:00 2001 From: Artem Medvedev Date: Tue, 24 Sep 2024 15:19:13 +0200 Subject: [PATCH 1/4] fix: make sure log consumers are stopped before deleting container Closes #719 --- .../src/core/containers/async_container.rs | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/testcontainers/src/core/containers/async_container.rs b/testcontainers/src/core/containers/async_container.rs index 44e2417a..727bb34b 100644 --- a/testcontainers/src/core/containers/async_container.rs +++ b/testcontainers/src/core/containers/async_container.rs @@ -1,6 +1,9 @@ use std::{fmt, net::IpAddr, pin::Pin, str::FromStr, sync::Arc, time::Duration}; -use tokio::io::{AsyncBufRead, AsyncReadExt}; +use tokio::{ + io::{AsyncBufRead, AsyncReadExt}, + task::JoinHandle, +}; use tokio_stream::StreamExt; use crate::{ @@ -41,6 +44,7 @@ pub struct ContainerAsync { pub(super) docker_client: Arc, #[allow(dead_code)] network: Option>, + log_handler: Option>, dropped: bool, } @@ -57,18 +61,19 @@ where network: Option>, ) -> Result> { let log_consumers = std::mem::take(&mut container_req.log_consumers); - let container = ContainerAsync { + let mut container = ContainerAsync { id, image: container_req, docker_client, network, + log_handler: None, dropped: false, }; if !log_consumers.is_empty() { let mut logs = container.docker_client.logs(&container.id, true); let container_id = container.id.clone(); - tokio::spawn(async move { + let log_handler = tokio::spawn(async move { while let Some(result) = logs.next().await { match result { Ok(record) => { @@ -85,6 +90,8 @@ where } } }); + + container.log_handler.replace(log_handler); } let ready_conditions = container.image().ready_conditions(); @@ -356,13 +363,22 @@ where let id = self.id.clone(); let client = self.docker_client.clone(); let command = self.docker_client.config.command(); + let log_handler = self.log_handler.take(); let drop_task = async move { log::trace!("Drop was called for container {id}, cleaning up"); match command { env::Command::Remove => { + if let Some(handle) = log_handler { + if let Err(e) = handle.await { + log::error!("Failed to wait log consumers to finish: {e}"); + } + if let Err(e) = client.stop(&id).await { + log::error!("Failed to stop container on drop: {e}") + } + } if let Err(e) = client.rm(&id).await { - log::error!("Failed to remove container on drop: {}", e); + log::error!("Failed to remove container on drop: {e}"); } } env::Command::Keep => {} From baf5a1ab289bc5d7859884ae0e06f80d04c2b3e0 Mon Sep 17 00:00:00 2001 From: Artem Medvedev Date: Thu, 30 Oct 2025 09:59:01 -0500 Subject: [PATCH 2/4] wip --- testcontainers/src/core/containers/async_container.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testcontainers/src/core/containers/async_container.rs b/testcontainers/src/core/containers/async_container.rs index b5aa6e84..bcdc68dd 100644 --- a/testcontainers/src/core/containers/async_container.rs +++ b/testcontainers/src/core/containers/async_container.rs @@ -258,7 +258,7 @@ where match command { env::Command::Remove => { if let Some(handle) = log_handler { - if let Err(e) = client.stop(&id).await { + if let Err(e) = client.stop(&id, None).await { log::error!("Failed to stop container on drop: {e}") } if let Err(e) = handle.await { From d709eeb4eaa68b442e5025517603d33b62947eaa Mon Sep 17 00:00:00 2001 From: Artem Medvedev Date: Thu, 30 Oct 2025 10:33:25 -0500 Subject: [PATCH 3/4] wip --- testcontainers/src/core/containers/async_container.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/testcontainers/src/core/containers/async_container.rs b/testcontainers/src/core/containers/async_container.rs index bcdc68dd..57b23b29 100644 --- a/testcontainers/src/core/containers/async_container.rs +++ b/testcontainers/src/core/containers/async_container.rs @@ -1,5 +1,6 @@ use std::{fmt, ops::Deref, sync::Arc}; +use tokio::task::JoinHandle; use tokio_stream::StreamExt; #[cfg(feature = "host-port-exposure")] From cbf57fdfcf1c4647f62a9c3d04a43b9071334fcd Mon Sep 17 00:00:00 2001 From: Artem Medvedev Date: Thu, 30 Oct 2025 10:55:03 -0500 Subject: [PATCH 4/4] wip --- testcontainers/src/core/containers/async_container.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testcontainers/src/core/containers/async_container.rs b/testcontainers/src/core/containers/async_container.rs index 57b23b29..43019c10 100644 --- a/testcontainers/src/core/containers/async_container.rs +++ b/testcontainers/src/core/containers/async_container.rs @@ -82,7 +82,7 @@ where let reuse = container_req.reuse(); let log_consumers = std::mem::take(&mut container_req.log_consumers); - let container = ContainerAsync { + let mut container = ContainerAsync { raw: raw::RawContainer::new(id, docker_client), image: container_req, network,