Skip to content

Fix subprocess registry ownership during close - #614

Open
somethingwithproof wants to merge 1 commit into
Cacti:developfrom
somethingwithproof:fix/subprocess-ownership
Open

Fix subprocess registry ownership during close#614
somethingwithproof wants to merge 1 commit into
Cacti:developfrom
somethingwithproof:fix/subprocess-ownership

Conversation

@somethingwithproof

@somethingwithproof somethingwithproof commented Sep 4, 2026

Copy link
Copy Markdown
Member

Summary

  • close and detach each subprocess registry entry atomically under ListMutex
  • transfer the detached node to exactly one closer and make cancellation cleanup release only that owned node
  • reject duplicate close attempts with EBADF before descriptor reuse
  • guard the timeout path against sending SIGKILL for an invalid child PID
  • leave php.c unchanged

Validation

  • Docker + AddressSanitizer: 40/40 tests, repeated 50 times
  • Docker + ThreadSanitizer: 40/40 tests, repeated 50 times
  • cppcheck on nft_popen.c and poller.c
  • git diff --check
  • GitHub Actions: GCC, Clang, sanitizers, coverage, distcheck, fuzz, SNMPv3, Rocky Linux, and flawfinder all succeeded

The cancellation test uses child readiness and the registry transition rather than a fixed sleep. It deliberately cleans up the pre-existing cancelled-child lifecycle; bounded child shutdown remains in PR #597 and is not duplicated here. PR #597 should rebase after this invariant lands.

Closes #610

Detach the subprocess entry under ListMutex before exposing it to close, wait, or cancellation cleanup. A second closer now receives EBADF instead of sharing a pointer that can be freed concurrently.

Keep cancellation disabled through descriptor close so cleanup cannot close a reused descriptor number. Cover concurrent closers and cancellation against the shipped nft_popen object.

Closes Cacti#610

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

Copilot AI 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.

🟢 Approval recommended

The changes correctly enforce exclusive registry ownership under ListMutex, add targeted tests for the new invariants (including cancellation), and include a safety guard against dangerous kill() PID values.

Pull request overview

This PR hardens nft_pclose()’s subprocess registry handling so that closing a nft_popen() descriptor transfers exclusive ownership to exactly one closer, preventing duplicate close/wait/free races and aligning behavior with issue #610’s acceptance criteria.

Changes:

  • Refactors nft_pclose() to atomically detach+close the registry entry under ListMutex and free only the detached node via the cleanup handler.
  • Adds unit tests that exercise concurrent close ownership, cancellation cleanup behavior, and preservation of pthread cancellation state on early EBADF.
  • Guards the timeout kill path in exec_poll() against invalid/unsafe PIDs and records the fix in CHANGELOG.
File summaries
File Description
tests/unit/test_linked.c Adds concurrency/cancellation-focused unit tests for nft_pclose()/registry ownership semantics.
poller.c Prevents kill() from being called with invalid PIDs on NIFTY POPEN timeout.
nft_popen.c Introduces atomic detach-and-take helper and updates nft_pclose() cleanup ownership model.
CHANGELOG Documents issue #610 fix.
Review details
  • Files reviewed: 4/4 changed files
  • Comments generated: 0
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Make nft_pclose take exclusive ownership of subprocess entries

5 participants