fix(guardian): prevent approval review stack overflows - #26663
Closed
fcoury-oai wants to merge 1 commit into
Closed
Conversation
fcoury-oai
marked this pull request as ready for review
June 5, 2026 19:50
Contributor
|
Closing this pull request because it has had no updates for more than 14 days. If you plan to continue working on it, feel free to reopen or open a new PR. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Guardian approval review can abort the entire Codex process with a stack overflow while opening a permission request.
This was reproduced on macOS through the multi-directory/worktree flow:
git worktree addsucceeds.Reviewing approval request, the process aborts:The crash happens while Guardian materializes and loads its nested review session, before the permission request can complete. A Rust stack overflow aborts the process rather than returning a recoverable Guardian denial, so the user loses the active Codex process even though the worktree itself was created successfully.
Why the production stack configuration does not prevent this
Codex already gives its normal production execution paths larger stacks:
codex-arg0configures a 16 MiB stack budget for both the namedcodex-mainthread and Tokio worker threads.RUST_MIN_STACKor otherwise change native thread stack sizes.std::thread::spawn.Rust currently gives ordinary spawned threads a 2 MiB default stack on Tier-1 platforms unless
RUST_MIN_STACKorstd::thread::Builder::stack_sizeoverrides it. A newly spawned Guardian thread does not inherit the 16 MiB allocation ofcodex-mainor the Tokio worker that created it. Release mode and installation through the npm wrapper therefore do not remove this failure mode.The Guardian thread also builds a current-thread Tokio runtime and drives the complete nested approval-review future on that same OS stack. That makes this thread boundary the appropriate place to define the stack requirement explicitly.
What Changed
std::thread::spawnwithstd::thread::Builderfor Guardian approval reviews.guardian-approval-request-reviewso panic and native-thread diagnostics identify the failing subsystem.ReviewDecision::Deniedas before;This does not change Guardian policy, permission semantics, session reuse, approval decisions, workspace mutation behavior, thread count, or the npm launcher. It only changes the stack budget and diagnostic name of the existing per-review thread.
Why 4 MiB
Four MiB doubles Rust's current Tier-1 spawned-thread default while keeping the change local to the thread that has the demonstrated production requirement. It also matches the stack size already used by the Guardian parallel-review regression harness.
Using
Builder::stack_sizeis preferable to relying onRUST_MIN_STACKhere because it documents the requirement at the ownership boundary and does not increase the stack allocation of every Rust-created thread in the process. It also behaves consistently for source builds and packaged native binaries.The existing code already creates one OS thread per approval review. This PR does not increase concurrency or thread lifetime; it only raises that thread's stack reservation from the platform/Rust default to 4 MiB.
Prior Art
RUST_MIN_STACK=8388608for Cargo, nextest, and Bazel test entry points after localized async-future and per-test fixes kept recurring. That protects test-runner threads, not production Guardian threads.codex-mainon the same 16 MiB stack budget as Tokio workers after/clearcould overflow the smaller process-main stack. It is the closest production precedent for making a stack-heavy execution boundary explicit. The Guardian review thread is created below that boundary and therefore needs its own setting.SIGABRTclass by moving config loading off a deep TUI caller stack. It concerns a different call path and does not cover Guardian approval review.How to Test
Manual regression path
codex-rsdirectory.git worktree addoperation.SIGABRT.Focused non-happy path
Automated validation
just test -p codex-core guardian_parallel_reviews_fork_from_last_committed_trunk_historyjust fix -p codex-coreNo external documentation update is needed because this is an internal runtime reliability fix with no user-facing API or configuration change.