fix(process): unify subprocess ownership and child lifecycle safety - #614
Open
somethingwithproof wants to merge 15 commits into
Open
fix(process): unify subprocess ownership and child lifecycle safety#614somethingwithproof wants to merge 15 commits into
somethingwithproof wants to merge 15 commits into
Conversation
xmacan
approved these changes
Sep 4, 2026
Contributor
There was a problem hiding this comment.
🟢 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 underListMutexand 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 inCHANGELOG.
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.
bmfmancini
approved these changes
Sep 4, 2026
This was referenced Sep 5, 2026
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>
PR Cacti#542 removed both while adding unrelated poller fixes; its branch predated only guard was a shell script that grepped the source, and it was deleted in the same commit. An inherited pipe write end keeps a script's reader from seeing EOF, so the thread blocks to script_timeout for a device that answered. The unbounded waitpid has no timeout at all, and the thread holds its available_scripts token while it waits. The php.c reap survived Cacti#542 and is better than what was removed, so only its pipes needed the flag. Both callers now share one helper, covered by six tests against the shipped object: two of them fail if the close-on-exec goes away again. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
Collect the child-process corrections from Cacti#597 after the foundational close-on-exec restoration. Preserve cancellation-safe abandoned-child handling, descriptor failure contracts, PHP resource ownership, startup restart bounds, and persistent SIGPIPE handling. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
Extract the production-linked PHP runtime suite, its script-server fixture, the portable linker-wrap probe, and the structural regression guard from Cacti#597. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
Share the reviewed spawn-attribute helper between nft_popen and the PHP script server without pulling the overlapping nft_pclose ownership rewrite from Cacti#597. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
Map the BSD ICMP_UNREACH name to the Linux spelling used by the shared linked-object regression suite. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
Check the shared close-on-exec helper and bounded PHP handshake without pulling the poll_host and ICMP assertions assigned to other replacement branches. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
somethingwithproof
force-pushed
the
fix/subprocess-ownership
branch
from
September 6, 2026 08:42
25d88c3 to
aba501b
Compare
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
vfork/execvechild setup withposix_spawnand explicit file actionsThis folds the child-process lifecycle portion of #597 into the narrower ownership PR. It does not absorb unrelated poll-host, SQL, SNMP, ICMP, or build-infrastructure work.
Review-driven corrections
dup()in both read and write stdio-collision branchesValidation
make check, 6/6 targets passed with no skips, includingtest_php_runtime42reachedpoller_outputand no zombie remainedmake check: 5/5 available binaries passed; GNU--wrapruntime suite is Linux-onlygit diff --checkpassedCloses #610.