optimize: terminal spawn lifecycle to eliminate output race condition

Move PTY spawn from context layer to view layer so event subscription
happens before spawn, preventing loss of initial terminal output.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
xintaofei
2026-04-02 13:55:38 +08:00
parent d0e0aad525
commit b2d10fa008
8 changed files with 143 additions and 60 deletions

View File

@@ -69,11 +69,14 @@ pub(crate) fn prepare_credential_env(
pub async fn terminal_spawn(
working_dir: String,
initial_command: Option<String>,
terminal_id: Option<String>,
manager: State<'_, TerminalManager>,
app_handle: tauri::AppHandle,
window: tauri::WebviewWindow,
) -> Result<String, TerminalError> {
let terminal_id = uuid::Uuid::new_v4().to_string();
let terminal_id = terminal_id
.filter(|id| !id.is_empty() && id.len() <= 256)
.unwrap_or_else(|| uuid::Uuid::new_v4().to_string());
let app_data_dir = app_handle
.path()

View File

@@ -162,6 +162,17 @@ impl TerminalManager {
opts: SpawnOptions,
emitter: EventEmitter,
) -> Result<String, TerminalError> {
// Reject duplicate IDs to prevent orphaning an existing PTY process.
{
let terminals = self.terminals.lock().unwrap();
if terminals.contains_key(&opts.terminal_id) {
return Err(TerminalError::SpawnFailed(format!(
"terminal id '{}' already exists",
opts.terminal_id
)));
}
}
let pty_system = native_pty_system();
let pair = pty_system

View File

@@ -18,6 +18,7 @@ use crate::terminal::types::TerminalInfo;
pub struct TerminalSpawnParams {
pub working_dir: String,
pub initial_command: Option<String>,
pub terminal_id: Option<String>,
}
#[derive(Deserialize)]
@@ -50,7 +51,10 @@ pub async fn terminal_spawn(
Json(params): Json<TerminalSpawnParams>,
) -> Result<Json<String>, AppCommandError> {
let manager = &state.terminal_manager;
let terminal_id = uuid::Uuid::new_v4().to_string();
let terminal_id = params
.terminal_id
.filter(|id| !id.is_empty() && id.len() <= 256)
.unwrap_or_else(|| uuid::Uuid::new_v4().to_string());
let extra_env = prepare_credential_env(&state.data_dir);