Fix stopping one project killing all project terminal sessions
All checks were successful
Build App / build-windows (push) Successful in 3m11s
Build App / build-linux (push) Successful in 6m15s

close_all_sessions() was called when stopping/removing/rebuilding a
project, which shut down exec sessions for every project. Track
container_id per session and use close_sessions_for_container() to
only close sessions belonging to the target project.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-27 19:54:44 +00:00
parent 839dd9f105
commit 0a4f207556
2 changed files with 19 additions and 5 deletions

View File

@@ -28,14 +28,12 @@ pub async fn remove_project(
// Stop and remove container if it exists
if let Some(project) = state.projects_store.get(&project_id) {
if let Some(ref container_id) = project.container_id {
state.exec_manager.close_sessions_for_container(container_id).await;
let _ = docker::stop_container(container_id).await;
let _ = docker::remove_container(container_id).await;
}
}
// Close any exec sessions
state.exec_manager.close_all_sessions().await;
state.projects_store.remove(&project_id)
}
@@ -166,7 +164,7 @@ pub async fn stop_project_container(
state.projects_store.update_status(&project_id, ProjectStatus::Stopping)?;
// Close exec sessions for this project
state.exec_manager.close_all_sessions().await;
state.exec_manager.close_sessions_for_container(container_id).await;
docker::stop_container(container_id).await?;
state.projects_store.update_status(&project_id, ProjectStatus::Stopped)?;
@@ -187,7 +185,7 @@ pub async fn rebuild_project_container(
// Remove existing container
if let Some(ref container_id) = project.container_id {
state.exec_manager.close_all_sessions().await;
state.exec_manager.close_sessions_for_container(container_id).await;
let _ = docker::stop_container(container_id).await;
docker::remove_container(container_id).await?;
state.projects_store.set_container_id(&project_id, None)?;

View File

@@ -9,6 +9,7 @@ use super::client::get_docker;
pub struct ExecSession {
pub exec_id: String,
pub container_id: String,
pub input_tx: mpsc::UnboundedSender<Vec<u8>>,
shutdown_tx: mpsc::Sender<()>,
}
@@ -140,6 +141,7 @@ impl ExecSessionManager {
let session = ExecSession {
exec_id,
container_id: container_id.to_string(),
input_tx,
shutdown_tx,
};
@@ -175,6 +177,20 @@ impl ExecSessionManager {
}
}
pub async fn close_sessions_for_container(&self, container_id: &str) {
let mut sessions = self.sessions.lock().await;
let ids_to_close: Vec<String> = sessions
.iter()
.filter(|(_, s)| s.container_id == container_id)
.map(|(id, _)| id.clone())
.collect();
for id in ids_to_close {
if let Some(session) = sessions.remove(&id) {
session.shutdown();
}
}
}
pub async fn close_all_sessions(&self) {
let mut sessions = self.sessions.lock().await;
for (_, session) in sessions.drain() {