mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
Reduce stack pressure in session startup and config rebuilds (#25844)
## Why `/clear` starts a fresh thread with `InitialHistory::Cleared`, which re-enters the thread/session startup path. That path now builds large async futures through `ThreadManagerState::spawn_thread_with_source`, `Codex::spawn`, and `Session::new`. Separately, TUI config rebuilds for cwd and permission-profile changes build a similarly heavy `ConfigBuilder::build()` future inside the app task. In debug and Bazel runs, those call chains can put enough state on the caller stack to abort before startup or config refresh completes. This change keeps the behavior the same while moving the heaviest future frames off the caller stack. ## What changed - Box `Codex::spawn(...)` in `codex-rs/core/src/thread_manager.rs` before awaiting it from `spawn_thread_with_source`. - Box `Session::new(...)` in `codex-rs/core/src/session/mod.rs` before awaiting it from `Codex::spawn_internal`. - Route `ConfigBuilder::build()` through a small `tokio::spawn` helper in `codex-rs/tui/src/app/config_persistence.rs` so cwd and permission-profile config rebuilds run on a runtime worker stack while preserving error context. ## Verification CI is running on the PR. No new targeted tests were added. This is a mechanical stack-pressure reduction that keeps the existing behavior and error propagation intact.
This commit is contained in:
committed by
GitHub
Unverified
parent
33273e4258
commit
1dd731305a
@@ -625,7 +625,7 @@ impl Codex {
|
||||
let session_source_clone = session_configuration.session_source.clone();
|
||||
let (agent_status_tx, agent_status_rx) = watch::channel(AgentStatus::PendingInit);
|
||||
|
||||
let session = Session::new(
|
||||
let session = Box::pin(Session::new(
|
||||
session_configuration,
|
||||
config.clone(),
|
||||
installation_id,
|
||||
@@ -647,7 +647,7 @@ impl Codex {
|
||||
parent_rollout_thread_trace,
|
||||
attestation_provider,
|
||||
multi_agent_version,
|
||||
)
|
||||
))
|
||||
.await
|
||||
.map_err(|e| {
|
||||
error!("Failed to create session: {e:#}");
|
||||
|
||||
@@ -1308,7 +1308,7 @@ impl ThreadManagerState {
|
||||
.await;
|
||||
let CodexSpawnOk {
|
||||
codex, thread_id, ..
|
||||
} = Codex::spawn(CodexSpawnArgs {
|
||||
} = Box::pin(Codex::spawn(CodexSpawnArgs {
|
||||
config,
|
||||
installation_id: self.installation_id.clone(),
|
||||
auth_manager,
|
||||
@@ -1336,7 +1336,7 @@ impl ThreadManagerState {
|
||||
thread_store: Arc::clone(&self.thread_store),
|
||||
attestation_provider: self.attestation_provider.clone(),
|
||||
inherited_multi_agent_version: multi_agent_version,
|
||||
})
|
||||
}))
|
||||
.await?;
|
||||
let new_thread = self
|
||||
.finalize_thread_spawn(codex, thread_id, tracked_session_source)
|
||||
|
||||
@@ -14,19 +14,32 @@ pub(super) struct WindowsSetupPermissions {
|
||||
pub(super) workspace_roots: Vec<AbsolutePathBuf>,
|
||||
}
|
||||
|
||||
async fn build_config_on_runtime_worker(
|
||||
builder: ConfigBuilder,
|
||||
error_context: String,
|
||||
) -> Result<Config> {
|
||||
match tokio::spawn(async move { builder.build().await }).await {
|
||||
Ok(build_result) => build_result.wrap_err(error_context),
|
||||
Err(err) if err.is_panic() => std::panic::resume_unwind(err.into_panic()),
|
||||
Err(err) => Err(err).wrap_err_with(|| format!("{error_context} task failed")),
|
||||
}
|
||||
}
|
||||
|
||||
impl App {
|
||||
pub(super) async fn rebuild_config_for_cwd(&self, cwd: PathBuf) -> Result<Config> {
|
||||
let mut overrides = self.harness_overrides.clone();
|
||||
overrides.cwd = Some(cwd.clone());
|
||||
let cwd_display = cwd.display().to_string();
|
||||
ConfigBuilder::default()
|
||||
let builder = ConfigBuilder::default()
|
||||
.codex_home(self.config.codex_home.to_path_buf())
|
||||
.cli_overrides(self.cli_kv_overrides.clone())
|
||||
.harness_overrides(overrides)
|
||||
.loader_overrides(self.loader_overrides.clone())
|
||||
.build()
|
||||
.await
|
||||
.wrap_err_with(|| format!("Failed to rebuild config for cwd {cwd_display}"))
|
||||
.loader_overrides(self.loader_overrides.clone());
|
||||
build_config_on_runtime_worker(
|
||||
builder,
|
||||
format!("Failed to rebuild config for cwd {cwd_display}"),
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub(super) async fn rebuild_config_for_permission_profile(
|
||||
@@ -38,16 +51,16 @@ impl App {
|
||||
overrides.sandbox_mode = None;
|
||||
overrides.permission_profile = None;
|
||||
overrides.default_permissions = Some(profile_id.to_string());
|
||||
ConfigBuilder::default()
|
||||
let builder = ConfigBuilder::default()
|
||||
.codex_home(self.config.codex_home.to_path_buf())
|
||||
.cli_overrides(self.cli_kv_overrides.clone())
|
||||
.harness_overrides(overrides)
|
||||
.loader_overrides(self.loader_overrides.clone())
|
||||
.build()
|
||||
.await
|
||||
.wrap_err_with(|| {
|
||||
format!("Failed to rebuild config for permission profile {profile_id}")
|
||||
})
|
||||
.loader_overrides(self.loader_overrides.clone());
|
||||
build_config_on_runtime_worker(
|
||||
builder,
|
||||
format!("Failed to rebuild config for permission profile {profile_id}"),
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
|
||||
Reference in New Issue
Block a user