Skip to content

fix: terminate signal-owned publication process trees - #625

Open
mldangelo-oai wants to merge 4 commits into
mainfrom
mdangelo/codex/fix-publication-signal-ownership
Open

fix: terminate signal-owned publication process trees#625
mldangelo-oai wants to merge 4 commits into
mainfrom
mdangelo/codex/fix-publication-signal-ownership

Conversation

@mldangelo-oai

Copy link
Copy Markdown
Collaborator

Summary

When a connected publication ignored cooperative cancellation, a later terminal signal could exit the CLI without first stopping the publication process tree. This change gives the CLI a synchronous forced-exit path for signal-owned publication processes while preserving recovery evidence and caller ownership for SDK publications without a signal.

This pull request is stacked on #624.

Changes

  • Keep active signal-owned publication children in an internal process registry and remove them on every terminal path.
  • Give signal-owned POSIX publishers their own process group, terminate that group synchronously on forced exit, and use synchronous Windows taskkill /PID ... /T /F for the equivalent tree operation.
  • Keep no-signal SDK publishers attached to and owned by the calling process.
  • Terminate registered publishers while CLI signal handlers are still installed, then remove the handlers immediately before the conventional forced exit.
  • Cover duplicate-signal debounce, different and delayed signal escalation, POSIX and Windows termination calls, resistant descendants, bounded failure cleanup, minimal child environments, and retained recovery evidence.

Testing

  • Original failing-first integration run: 6 passed, 3 failed, seed 1356491567.
  • Forced-kill oracle failing-first run: 0 passed, 1 failed, seed 1917048208.
  • Publication and signal suites: 119 passed, 0 failed, 1,396 assertions, seed 753168830.
  • Full TypeScript suite under umask 077: 1,700 passed, 28 expected skips, 0 failed, 22,308 assertions, seed 3195823917.
  • pnpm run types, pnpm run format, and git diff --check: passed.
  • Build and package pack/check/smoke: passed; the package checker validated 265 archive entries plus installed public imports, NodeNext types, CLI behavior, 113 bundled plugin files, bundled Codex, and nested-worker startup.
  • Three fresh read-only gpt-5.6-sol reviews at maximum reasoning on exact head ae7b2d70a06502459c939e47c54d0e619a266360: no actionable correctness findings.

Risk and rollout

The force helper remains internal to the publication module and is not exported from the package root. No public command or SDK option changes. POSIX tests assert the exact negative-process-group SIGKILL; Windows tests assert the exact synchronous taskkill executable and arguments, with hosted Windows CI providing the native platform gate. If taskkill itself fails, the existing direct-child fallback remains best effort.

Public disclosure review

  • No customer, partner, prospect, or user identities, data, or identifying details are included.
  • No credentials, personal data, private source, scan findings, or nonpublic links or tickets are included.
  • I reviewed the branch name, title, description, commits, changes, comments, logs, screenshots, attachments, and links for public disclosure.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Aug 24, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-08-24T03:24:58.330417Z ae7b2d7 Manual request
🔒 Security Review Completed 2026-08-24T03:25:33.607259Z ae7b2d7 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@mldangelo-oai

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Chef's kiss.

Reviewed commit: ae7b2d70a0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@kmbroai kmbroai left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Critical review

Reviewed head ae7b2d70a06502459c939e47c54d0e619a266360 against its declared stacked base, #624.

Recommendation: keep this fix; no new merge-blocking defect found in the reviewed changes. The necessary behavior is narrow: a second cancellation signal must terminate the publisher's process tree before the CLI exits. Otherwise the CLI can disappear while a connected publisher continues doing externally visible work. Applying escalation to connected publication as well as direct-API publication is warranted.

Correctness

The ownership boundary in runPublicationCodex is appropriate: only children with an explicit abort signal are registered and detached on POSIX. Ordinary signal-less SDK children remain attached to their caller. Cleanup removes both the registration and abort listener, and cancellation's final process-group kill handles descendants that outlive the direct child. In the CLI, force termination happens before signal handlers are removed and the injected exit runs; it does not merely schedule work that process exit would discard.

Necessity and simplification

Keep this as a cancellation/ownership patch rather than expanding it into a generic subprocess supervisor. A small registry is justified because final CLI exit cannot await a per-call cancellation promise. The shared process-group helper is already reused. The Windows synchronous and asynchronous taskkill paths have different lifecycle requirements, so combining them just to remove a few lines would obscure the reason for the synchronous path.

The same-signal delivery debounce and ordinary SDK ownership tests are useful counterexamples: “kill everything on every signal” would be a regression. Preserve those contracts when rebasing on the large #624 publication changes; passing this child PR does not independently validate all of that base's recovery logic.

Verification

Ran the checked-in publication-integration.test.ts and publish.test.ts: 76 passed, 0 failed on Linux, Bun 1.3.14 / Node 22.13.1 with cached dependencies. This includes actual descendant-process cancellation and the injected Windows taskkill command check. It was not a native Windows run, a clean dependency installation, or a live Linear publication.

faizan-oai
faizan-oai previously approved these changes Aug 24, 2026

@faizan-oai faizan-oai left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reviewed this PR's delta against #624, including signal-owned process-tree termination and no-signal SDK behavior. Focused tests and current-head CI pass. No blocking findings in this delta; the stack's merge order remains separate.

Base automatically changed from mdangelo/codex/fix-linear-publication-recovery to main August 25, 2026 00:20
@faizan-oai
faizan-oai dismissed their stale review August 25, 2026 00:20

The base branch was changed.

@github-actions github-actions Bot added the bug Something isn't working label Aug 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants