-
Notifications
You must be signed in to change notification settings - Fork 0
fix(hook)!: get the Stop path off the tree scan — 110s to 220ms #887
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
1c18277
333dff9
630d325
17dd86d
922f331
e04ca6d
4fbba77
bed7187
8acb68c
5f83fbe
e77de5b
b15fd0a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1452,6 +1452,52 @@ pub(crate) fn piped( | |
| )) | ||
| } | ||
|
|
||
| /// Start `program` with `args` and **do not wait** (CLOUD-1480). | ||
| /// | ||
| /// `piped`'s opposite number, and the pair is the whole of this module's | ||
| /// contract: `piped` runs a child for its ANSWER, this one runs a child because | ||
| /// the work must outlive the caller. A mediated boundary has a per-call budget | ||
| /// the work cannot fit in, so it starts the child and returns; waiting is the | ||
| /// defect the caller exists to remove, which is why nothing here is returned to | ||
| /// wait on. | ||
| /// | ||
| /// Placed HERE rather than at the caller for `spawn-adapters`' reason: `lib.rs` | ||
| /// is not on that table and the table's own comment refuses to put it there, | ||
| /// because placing the CLI dispatch would admit every future spawn in the | ||
| /// crate's largest file at once. The caller composes the argv — which flags mean | ||
| /// what is its business — and this module owns the process. | ||
| /// | ||
| /// `env` is applied after the inherited environment, so a caller marks the child | ||
| /// without reaching for a second mechanism. | ||
| /// | ||
| /// Silent: no `Result`, because there is no caller that could act on the | ||
| /// difference. A boundary that cannot start its own background work must not | ||
| /// turn that into a verdict about the call it was mediating. | ||
| #[expect( | ||
| clippy::disallowed_types, | ||
| reason = "stays: the detached child IS the point (CLOUD-1480). `piped` above is the waiting path and is exactly what this must not be; both spawns are the placed adapter's" | ||
| )] | ||
| pub(crate) fn detached(program: &Path, args: &[String], env: &[(&str, &str)]) { | ||
| let mut builder = Command::new(program.as_os_str()); | ||
| builder | ||
| .args(args) | ||
| .stdin(Stdio::null()) | ||
| .stdout(Stdio::null()) | ||
| .stderr(Stdio::null()); | ||
| for (name, value) in env { | ||
| builder.env(name, value); | ||
| } | ||
| #[cfg(unix)] | ||
| { | ||
| use std::os::unix::process::CommandExt as _; | ||
| // Its own group, so a harness reaping the caller's group does not take | ||
| // this child with it. | ||
| builder.process_group(0); | ||
| } | ||
| // SPAWNED AND DROPPED. No `wait`, no `status`, no handle kept. | ||
| drop(builder.spawn()); | ||
| } | ||
|
|
||
|
Comment on lines
+1497
to
+1500
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win Surface failed state-record launches without blocking the Stop hook. 🤖 Prompt for AI Agents |
||
| /// This process's next dispatch number, for the live-capture key. | ||
| /// | ||
| /// The key has to name a *run*, not just a command: through the CLI there is | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win
🔎 Supported by static analysis
🌐 Web query:
Does Command::process_group(0) on Unix have a Windows equivalent for detaching a spawned child from the parent's console process group or job object?💡 Result:
There is no direct, single-flag equivalent to the Unix Command::process_group(0) on Windows because the underlying process models differ significantly [1][2][3]. On Unix, process groups are a kernel-level construct for signaling [4][5]; on Windows, the closest functional equivalent is the use of Job Objects, which provide hierarchical process tree management [1][6][7]. To achieve "detachment" or tree-wide management on Windows similar to Unix process group behavior, developers typically combine specific process creation flags with Job Objects [6][5][8]: 1. Detaching from Parent Console/Jobs: To prevent a child process from being terminated when the parent exits—or to escape a restrictive parent Job Object—you should use the CREATE_BREAKAWAY_FROM_JOB flag in your process creation flags [5][8]. Additionally, flags like DETACHED_PROCESS or CREATE_NO_WINDOW can be used to control the child's interaction with the parent's console [9][8][10]. 2. Managing Process Trees (The "Process Group" Equivalent): If your goal is to manage a group of processes (e.g., terminating an entire tree when the parent stops), you must manually create a Windows Job Object and assign the child process to it [2][3][6]. - Use CreateJobObject to create the object and SetInformationJobObject with the JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE limit [3][6][7]. - When you close the handle to this Job Object, the operating system automatically terminates all processes assigned to it, providing a mechanism similar to sending a signal to a Unix process group [3][6][7]. Many Rust libraries (such as the command-group crate) abstract these differences by implementing a trait that handles the OS-specific logic: calling process_group(0) on Unix and creating/assigning a Job Object on Windows [1][11][12]. If you are not using such a library, you must manually implement the Windows Job Object logic post-spawn [3][7].
Citations:
🤖 get_repo_knowledge executed:
get_repo_knowledge button-inc/batten /tmp/coderabbit-repo-knowledge/button-inc-batten-40f975cf/architectureLength of output: 41289
🏁 Script executed:
Repository: button-inc/batten
Length of output: 3850
🏁 Script executed:
Repository: button-inc/batten
Length of output: 50374
🏁 Script executed:
Repository: button-inc/batten
Length of output: 34047
Add Windows detachment flags that match the required guarantee.
exec::detachedruns the state-record scan after the hook returns. The Windows path currently sets no creation flags.CREATE_NEW_PROCESS_GROUPisolates console control events, but it does not escape a kill-on-close Job Object. If the scan must survive its caller, useCREATE_BREAKAWAY_FROM_JOBwhen the parent Job Object permits breakaway. AddCREATE_NEW_PROCESS_GROUPonly when console-signal isolation is also required, and handle breakaway denial becausespawnis currently ignored.🤖 Prompt for AI Agents