Skip to content

fix: allow fire-and-forget child processes - #1737

Merged
kurtisc merged 4 commits into
mainfrom
kurtisc/fire-forget
Sep 3, 2026
Merged

kurtisc merged 4 commits into
mainfrom
kurtisc/fire-forget

Conversation

@kurtisc

@kurtisc kurtisc commented Aug 25, 2026 •

Copy link
Copy Markdown
Contributor

Linked Issue

Closes #1274

Summary

  • Records the session ID of 'fire and forget' calls so they can be resolved to the command that launched them, meaning they be 'allow'ed
  • Forwards ^Z/^C to the detached child processes

MacOS only, as Linux doesn't detach these children.

Test Plan

New integration test
Steps to reproduce

Checklist

  • An issue exists and is linked above
  • All commits are signed-off, using DCO
  • All new code follows the project's coding standards (CLAUDE.md) and is covered by tests
  • Public-facing changes are paired with documentation updates

@github-actions github-actions Bot added bug Something isn't working nono-cli size/large labels Aug 25, 2026
@github-actions

github-actions Bot commented Aug 25, 2026 •

Copy link
Copy Markdown
Contributor

PR Review Summary

Size

Metric Value
Lines added +2208
Lines removed -64
Total changed 2272
Classification Large (> 300 lines)

Affected crates

  • crates/nono-cli — CLI changes. Verify argument parsing, flag documentation, and UX behaviour across supported platforms.

Blast radius — Contained

This PR touches: source code


Updated automatically on each push to this PR.

@kurtisc
kurtisc force-pushed the kurtisc/fire-forget branch from 1084400 to d9051f3 Compare August 26, 2026 13:08
@kurtisc
kurtisc force-pushed the kurtisc/fire-forget branch from d9051f3 to fa01fe6 Compare August 26, 2026 14:19
@kurtisc
kurtisc force-pushed the kurtisc/fire-forget branch from fa01fe6 to 2f06eb6 Compare August 26, 2026 15:40
@kurtisc
kurtisc force-pushed the kurtisc/fire-forget branch from 2f06eb6 to 057423a Compare August 27, 2026 12:58
@kurtisc
kurtisc force-pushed the kurtisc/fire-forget branch from 057423a to 52c9101 Compare August 27, 2026 12:58
@kurtisc
kurtisc force-pushed the kurtisc/fire-forget branch from 52c9101 to c915bae Compare August 27, 2026 13:43
@kurtisc
kurtisc force-pushed the kurtisc/fire-forget branch from c915bae to aa8aacc Compare August 27, 2026 14:33
@kurtisc
kurtisc marked this pull request as ready for review August 27, 2026 15:13

@nogent-nolabs-ai nogent-nolabs-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nogent code review

No blocking issues; 0 suggestions.

Findings: none flagged in scope.

Automated code + security review. CI already covers clippy, rustfmt, tests, cargo-audit and commit-lint.

@SequeI

SequeI commented Aug 27, 2026

Copy link
Copy Markdown
Member

@panga Might be worth a look to ensure it fixes your issue and workflow with Nono :)

@panga

panga commented Aug 27, 2026 •

Copy link
Copy Markdown
Contributor

I just tested this branch and it still didn't fix my issue, I found in the audit the same error denied xxxx caller=untrusted reason=Command 'unknown' is blocked: caller ancestry did not reach session root

Please note this is not a bash, it is a process tree like this:

nono
|___claude
       |_____status-line-script (called by claude every X seconds)
             |____status-background-refresh (this is the one denied)

Exercises `parent` backgrounding `child` and exiting immediately.

Signed-off-by: Kurtis Charnock <kurtis@nolabs.ai>
Mediated launches call setsid() pre-exec and record its session id, so a
severed caller still resolves to the command that launched it.

The session table is bounded with least-recently-used eviction.

Signed-off-by: Kurtis Charnock <kurtis@nolabs.ai>
Track each mediated child's requester pid and process group  on
ActiveChild, and relay SIGINT/SIGTERM/SIGHUP/ SIGQUIT to only the
mediated children whose requester belongs to the terminal's current
foreground process group.

Signed-off-by: Kurtis Charnock <kurtis@nolabs.ai>
resolve_url_open_command did the same parent-pid ancestry walk as
resolve_caller_with but lacked the session-lineage fallback the
latter already has, so a command whose lineage was severed (e.g. a
backgrounded launcher that already exited) was correctly attributed
for command execution but still denied when it tried to open a URL.

Signed-off-by: Kurtis Charnock <kurtis@nolabs.ai>
@kurtisc

kurtisc commented Sep 2, 2026

Copy link
Copy Markdown
Contributor Author

Hi @panga, apologies the first attempt didn't solve your problem. I've pushed an update, but the previous version also passed the repro steps on my machine. Would you be able to test this update too? Thanks

@panga

panga commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

@kurtisc it worked like a charm. great work! :shipit:

@SequeI SequeI left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm! feel free to merge

@kurtisc
kurtisc merged commit d1d232e into main Sep 3, 2026
17 checks passed
levonk pushed a commit to levonk/nono that referenced this pull request Sep 4, 2026
* test(cli): repro fire-and-forget denial (nolabs-ai#1274)

Exercises `parent` backgrounding `child` and exiting immediately.

Signed-off-by: Kurtis Charnock <kurtis@nolabs.ai>

* fix(cli): attribute severed macOS orphans (nolabs-ai#1274)

Mediated launches call setsid() pre-exec and record its session id, so a
severed caller still resolves to the command that launched it.

The session table is bounded with least-recently-used eviction.

Signed-off-by: Kurtis Charnock <kurtis@nolabs.ai>

* fix(cli): relay Ctrl-C/Ctrl-Z to setsid'd mediated children

Track each mediated child's requester pid and process group  on
ActiveChild, and relay SIGINT/SIGTERM/SIGHUP/ SIGQUIT to only the
mediated children whose requester belongs to the terminal's current
foreground process group.

Signed-off-by: Kurtis Charnock <kurtis@nolabs.ai>

* fix(cli): resolve URL-open requests via session lineage

resolve_url_open_command did the same parent-pid ancestry walk as
resolve_caller_with but lacked the session-lineage fallback the
latter already has, so a command whose lineage was severed (e.g. a
backgrounded launcher that already exited) was correctly attributed
for command execution but still denied when it tried to open a URL.

Signed-off-by: Kurtis Charnock <kurtis@nolabs.ai>

---------

Signed-off-by: Kurtis Charnock <kurtis@nolabs.ai>
@SequeI
SequeI deleted the kurtisc/fire-forget branch September 4, 2026 14:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working nono-cli size/large

Projects

None yet

Development

Successfully merging this pull request may close these issues.

tool-sandbox denies fire-and-forget child

3 participants