Skip to content

fix(processtree): walk container branches under the creator lock - #1048

Merged
matthyx merged 1 commit into
kubescape:mainfrom
DeathGun44:fix/processtree-branch-race
Oct 24, 2026
Merged

matthyx merged 1 commit into
kubescape:mainfrom
DeathGun44:fix/processtree-branch-race

Conversation

@DeathGun44

@DeathGun44 DeathGun44 commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

Overview

GetContainerProcessTree walks the process map holding only the manager lock (process_tree_manager.go#L87-L91), while exit cleanup reparents children and writes PPID and Pcomm holding only the creator lock (exit_manager.go#L309-L311). They run in separate goroutines (event enrichment and the exit cleanup loop), so go test -race flags it.

The creator already has GetPidBranch, which takes its own lock. This adds it to the ProcessTreeCreator interface and calls it from the manager instead. Lock order stays manager then creator, same as ReportEvent, and cache hits still return before taking any lock.

Pcomm is a string, so a racing read isn't safe in Go. I haven't seen a crash or a wrong alert from it though.

New test TestManager_GetContainerProcessTree_ConcurrentExitCleanup reads branches while exit cleanup reparents. It fails with -race on main and passes with the fix.

This touches the same function as #1047, on different lines, so the two don't conflict.

How to Test

go test -race -count=10 ./pkg/processtree/...

Summary by CodeRabbit

  • Bug Fixes
    • Improved the reliability of process-tree retrieval when process exit cleanup happens at the same time. The requested process branch is now read consistently during cleanup, reducing the chance of an inconsistent result.
    • Added coverage for concurrent process-tree requests and exit cleanup.

GetContainerProcessTree walked the process map under the manager lock
only, while exit cleanup reparents children under the creator lock only.
Route the walk through the creator's existing GetPidBranch so both sides
take the same lock.

Signed-off-by: DeathGun44 <krishnamewara841@gmail.com>
@coderabbitai

coderabbitai Bot commented Oct 24, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 4ae043e8-4220-4826-b61c-35b3f0cf9286
Commits

Reviewing files that changed from the base of the PR and between d4bb9db and dc64635.

Files selected for processing: 4
  • pkg/processtree/creator/processtree_creator.go
  • pkg/processtree/creator/processtree_creator_interface.go
  • pkg/processtree/process_tree_manager.go
  • pkg/processtree/process_tree_manager_test.go

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.

Walkthrough

The manager now retrieves PID branches through the creator API, whose contract states that the walk occurs under the creator’s lock. A new test runs lookups during concurrent parent exit cleanup.

Changes: PID Branch Retrieval

Layer / File(s) Summary
Creator-mediated PID branch lookup
pkg/processtree/creator/processtree_creator_interface.go, pkg/processtree/process_tree_manager.go, pkg/processtree/creator/processtree_creator.go, pkg/processtree/process_tree_manager_test.go
The creator interface adds GetPidBranch, and the manager delegates branch retrieval to it. The method comment describes the lock held during the walk. A new test runs lookups while parent processes exit.

Priority: Normal

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

Suggested reviewers: matthyx

Merge Risk: Minimal · up to dc646

No merge-blocking issue is established for the locked process-tree lookup change; run the reported race test as part of normal checks.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 2 functions across 4 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title "fix(processtree): walk container branches under the creator lock" matches the main change. The PR switches GetContainerProcessTree to the creator's GetPidBranch, which takes the creator loc…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Title check

Explanation

The title "fix(processtree): walk container branches under the creator lock" matches the main change. The PR switches GetContainerProcessTree to the creator's GetPidBranch, which takes the creator lock, so branch reads and exit-cleanup reparenting use the same lock. The raw summary confirms the interface addition, the manager call-site change, the comment update, and the new concurrency test. The title is specific, concise, and in conventional-commit form.

Finishing Touches: 💡 1
🧪 Generate unit tests (beta)
  • Create a new PR
🛠️ Fix failing CI checks: 💡
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@matthyx matthyx 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.

Approve: this is a needed, narrowly scoped synchronization fix. Reviewed head dc64635ef02ffe6467ae347d1784963712ef4366 against main at d4bb9dbf3212880c7e7b1cc0d429823f1d9b0b8f.

The target branch walks mutable process nodes under the manager lock, but background exit cleanup independently writes child PPID/Pcomm under the creator lock (creator/exit_manager.go:121–143,309–313). The safe map protects map operations, not the pointed-to fields. Routing the walk through the existing creator accessor holds its read lock through ancestry traversal and branch copying. Lock order remains manager → creator → container, matching event handling; cleanup does not acquire the manager lock. Returned nodes and child maps are copied before unlocking. Cache behavior and error propagation are preserved. No correctness, security, lifecycle, or performance blocker found; both independent review lanes agree (architecture CLEAR).

Related history: #936 removed redundant node-copy allocations, #876 repaired exit lifecycle/PID reuse, #1027 repaired host ancestry, and #1045 added reparenting coverage. None supplies this shared-lock fix. #1047 targets failed-refresh cache invalidation on #1043's branch and is complementary. Closed #666 concerns lazy shim discovery; #667 concerns fork metadata and reparented Pcomm. Neither contains review discussion or an explicit rejection rationale. #521 was approved before a maintainer suggested closure, without a substantive rejection reason. These closures do not establish an objection to this fix. Repository-wide PR/issue searches covered processtree, process tree, GetPidBranch, GetContainerProcessTree, process_tree_manager.go, exit_manager, reparent, race, and creator lock, including open/closed/merged results, capped at 100 per query. The broad race query reached its cap; this is not an exhaustive proof of absence.

Nonblocking test improvement: process_tree_manager_test.go:177 ignores lookup results and relies on timing. Assert a successful branch and observed reparenting to guard against vacuous stress coverage. The interface gains a method already present on the production implementation; external custom implementations must add it. No dependency or data-format change.

Validation in an isolated, credential-free Linux container with Go 1.27.0: go test -mod=readonly -race -count=3 ./pkg/processtree/... and go vet -mod=readonly ./pkg/processtree/... passed. Replacing only the manager file with the exact target-branch version and running go test -mod=readonly -race -count=1 ./pkg/processtree -run '^TestManager_GetContainerProcessTree_ConcurrentExitCleanup$' failed with races between cleanup writes at exit_manager.go:309,311 and branch reads at container_processtree.go:246,248, confirming both necessity and regression coverage. An initial run with Go as container PID 1 passed the manager package but failed parent-PID-sensitive creator tests; the shell-parent rerun above passed all packages. Formatting checks passed. Semantic tooling could not resolve implementations reliably; no complete semantic-analysis result is claimed.

The reviewed commit's build/unit-test job, CodeQL, benchmark, and other component tests passed. Test_19's failed job timed out contacting Docker during cluster setup (exit 124), before executing the test; it is infrastructure failure. Full local agent build, full-repository lint, and live-cluster testing were not repeated.

Existing PR review and inline-comment lists were empty; the bot reported no actionable finding. Final open/head/base/draft/conflict checks are performed immediately before submission. No source branch changes or merge performed.

@matthyx
matthyx merged commit f6fcf46 into kubescape:main Oct 24, 2026
38 of 39 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

2 participants