subagent: close the start/continue TOCTOU race with an atomic reservation
This commit is contained in:
parent
c2fb3c6e3e
commit
561bd09618
3 changed files with 181 additions and 35 deletions
|
|
@ -1,5 +1,6 @@
|
|||
//! The MCP tool surface: `start` / `continue` / `interrupt`, served
|
||||
//! directly over streamable-http — no stdio bridge, no round-trip socket.
|
||||
//! The MCP tool surface: `start` / `continue` / `status` / `interrupt`,
|
||||
//! served directly over streamable-http — no stdio bridge, no round-trip
|
||||
//! socket.
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
|
|
@ -116,9 +117,11 @@ impl SubagentMcp {
|
|||
}
|
||||
|
||||
#[tool(
|
||||
description = "Signal a currently-running subagent session to stop. Only works while \
|
||||
it's actually running — there's no queued/pending state to cancel pre-emptively, \
|
||||
only running or not tracked at all. `force: true` for SIGKILL, otherwise SIGINT."
|
||||
description = "Signal a currently-running subagent session to stop. Only works once \
|
||||
it's actually running — a `start`/`continue` still in its brief window before the \
|
||||
process is confirmed spawned refuses interrupt too (nothing to signal yet; retry \
|
||||
shortly), same as a name with nothing tracked at all. `force: true` for SIGKILL, \
|
||||
otherwise SIGINT."
|
||||
)]
|
||||
fn interrupt(&self, Parameters(args): Parameters<InterruptArgs>) -> String {
|
||||
match session::interrupt(&self.state, &args.name, args.force) {
|
||||
|
|
@ -129,9 +132,10 @@ impl SubagentMcp {
|
|||
|
||||
#[tool(
|
||||
description = "Report whether a subagent is currently running — a zero-cost check that \
|
||||
never launches a process, unlike `continue`. Distinguishes running, idle (a session \
|
||||
exists but nothing is in flight — `continue` to give it another turn), and no such \
|
||||
session at all."
|
||||
never launches a process, unlike `continue`. Distinguishes running, starting (a \
|
||||
`start`/`continue` is in flight but not yet a confirmed spawn — this is normally \
|
||||
over in well under a second), idle (a session exists but nothing is in flight — \
|
||||
`continue` to give it another turn), and no such session at all."
|
||||
)]
|
||||
fn status(&self, Parameters(args): Parameters<StatusArgs>) -> String {
|
||||
match session::status(&self.state, &args.name) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue