diff options
| author | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-07-05 02:17:45 +0300 |
|---|---|---|
| committer | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-07-05 02:17:45 +0300 |
| commit | c78349f422139577f8d7bf5e07f84dcec5a48456 (patch) | |
| tree | 049cd25431acd355a1ab0923a2e0b6778f766e35 /src/session.rs | |
| parent | a4935886afffddf168bec4bbacacf9def6d1776b (diff) | |
fix: wait for server stop socket cleanup
Diffstat (limited to 'src/session.rs')
| -rw-r--r-- | src/session.rs | 61 |
1 files changed, 50 insertions, 11 deletions
diff --git a/src/session.rs b/src/session.rs index 34d202a5..4dfb2658 100644 --- a/src/session.rs +++ b/src/session.rs @@ -233,9 +233,37 @@ pub fn stop_session(name: Option<&str>) -> Result<SessionInfo, String> { stop_session_with_timeout(name, STOP_WAIT_TIMEOUT) } +pub(crate) fn stop_active_server() -> Result<(), String> { + let socket_path = active_api_socket_path(); + let client_socket_path = crate::server::socket_paths::client_socket_path(); + stop_socket_with_timeout( + socket_path.clone(), + vec![socket_path, client_socket_path], + STOP_WAIT_TIMEOUT, + "server", + ) +} + fn stop_session_with_timeout(name: Option<&str>, timeout: Duration) -> Result<SessionInfo, String> { - let deadline = Instant::now() + timeout; let socket_path = api_socket_path_for(name); + let client_socket_path = client_socket_path_for(name); + let label = format!("session {}", name.unwrap_or(DEFAULT_SESSION_NAME)); + stop_socket_with_timeout( + socket_path.clone(), + vec![socket_path, client_socket_path], + timeout, + &label, + )?; + Ok(session_info(name)) +} + +fn stop_socket_with_timeout( + socket_path: PathBuf, + stopped_socket_paths: Vec<PathBuf>, + timeout: Duration, + label: &str, +) -> Result<(), String> { + let deadline = Instant::now() + timeout; let request = serde_json::json!({ "id": "cli:session:stop", "method": "server.stop", @@ -243,8 +271,7 @@ fn stop_session_with_timeout(name: Option<&str>, timeout: Duration) -> Result<Se }); let stream = crate::ipc::connect_local_stream(&socket_path).map_err(|err| { format!( - "session {} is not running or cannot be reached at {}: {err}", - name.unwrap_or(DEFAULT_SESSION_NAME), + "{label} is not running or cannot be reached at {}: {err}", socket_path.display() ) })?; @@ -254,15 +281,19 @@ fn stop_session_with_timeout(name: Option<&str>, timeout: Duration) -> Result<Se return Err(error.to_string()); } } - if !wait_until_stopped_until(&socket_path, deadline) { + if !wait_until_stopped_until(&stopped_socket_paths, deadline) { + let reachable = reachable_socket_paths(&stopped_socket_paths); return Err(format!( - "session {} did not stop within {}ms; socket is still reachable at {}", - name.unwrap_or(DEFAULT_SESSION_NAME), + "{label} did not stop within {}ms; sockets are still reachable at {}", timeout.as_millis(), - socket_path.display() + reachable + .iter() + .map(|path| path.display().to_string()) + .collect::<Vec<_>>() + .join(", ") )); } - Ok(session_info(name)) + Ok(()) } pub fn delete_session(name: &str) -> Result<SessionInfo, String> { @@ -353,14 +384,22 @@ fn is_running_at(socket_path: &Path) -> bool { socket_path.exists() && crate::ipc::connect_local_stream(socket_path).is_ok() } -fn wait_until_stopped_until(socket_path: &Path, deadline: Instant) -> bool { +fn wait_until_stopped_until(socket_paths: &[PathBuf], deadline: Instant) -> bool { while Instant::now() < deadline { - if !is_running_at(socket_path) { + if socket_paths.iter().all(|path| !is_running_at(path)) { return true; } std::thread::sleep(STOP_WAIT_POLL.min(time_until(deadline))); } - !is_running_at(socket_path) + socket_paths.iter().all(|path| !is_running_at(path)) +} + +fn reachable_socket_paths(socket_paths: &[PathBuf]) -> Vec<PathBuf> { + socket_paths + .iter() + .filter(|path| is_running_at(path)) + .cloned() + .collect() } fn time_until(deadline: Instant) -> Duration { |
