Skip to content

🛡️ Sentinel: [MEDIUM] Fix Process Deadlocks#80

Open
NSEvent wants to merge 3 commits into
mainfrom
sentinel-fix-process-deadlocks-12262059625694813152
Open

🛡️ Sentinel: [MEDIUM] Fix Process Deadlocks#80
NSEvent wants to merge 3 commits into
mainfrom
sentinel-fix-process-deadlocks-12262059625694813152

Conversation

@NSEvent

@NSEvent NSEvent commented Jul 8, 2026

Copy link
Copy Markdown
Owner

🛡️ Sentinel: [MEDIUM] Fix Process Deadlocks

Vulnerability: Parent processes executing Process() (NSTask) with piped standard output/error were deadlocking if the child output exceeded the OS pipe buffer size (~64KB). The parent process called waitUntilExit() before reading the output, causing a classic IPC deadlock.

Impact: This is a DoS risk if an attacker can control or pad the output of commands executed by the application.

Fix: Always read all data from Pipe() objects (e.g., using readDataToEndOfFile()) before calling process.waitUntilExit(). This prevents the parent process from blocking on the exit signal while the child process blocks on a full pipe buffer.

Verification: The code changes were verified to fix the execution ordering issue without modifying the logic of what is read. Static verification passes.


PR created automatically by Jules for task 12262059625694813152 started by @NSEvent

Summary by CodeRabbit

  • Bug Fixes
    • Improved reliability when running background processes by reading command output before waiting for the process to finish.
    • Reduced the risk of app hangs caused by waiting on piped output too early.
    • Applied the same fix to process-tree checks and status lookups so command results are handled more safely.

Co-authored-by: NSEvent <44446865+NSEvent@users.noreply.github.com>
@google-labs-jules

Copy link
Copy Markdown
Contributor

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The change reorders subprocess output handling so pipe data is read via readDataToEndOfFile() before calling waitUntilExit(), applied in AutomationExecutor's runProcess and childPIDs(of:), and UniversalControlMouseRelay's tailscalePeerHosts(). A sentinel.md entry documents the underlying deadlock pattern.

Changes

Pipe read/wait ordering fix

Layer / File(s) Summary
Reorder pipe reads before waitUntilExit
TriggerKit/Sources/TriggerKitRuntime/AutomationExecutor.swift, XboxControllerMapper/XboxControllerMapper/Services/Input/UniversalControlMouseRelay.swift
Subprocess stdout/stderr and pgrep output are now fully read via readDataToEndOfFile() before calling waitUntilExit(), reversing the prior order in three call sites.
Deadlock pattern documentation
.Jules/sentinel.md
A new dated entry documents the NSTask/Pipe deadlock risk and recommends reading pipe data before waiting for process exit.

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

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant Process
  participant Pipe

  Caller->>Process: launch()
  Caller->>Pipe: readDataToEndOfFile()
  Pipe-->>Caller: output data
  Caller->>Process: waitUntilExit()
  Process-->>Caller: terminationStatus
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: fixing Process/NSTask deadlocks caused by piped stdout/stderr ordering.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch sentinel-fix-process-deadlocks-12262059625694813152

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.

@coderabbitai coderabbitai Bot 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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
XboxControllerMapper/XboxControllerMapper/Services/Input/UniversalControlMouseRelay.swift (1)

1400-1410: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Unread stderr pipe can still deadlock.

process.standardError = Pipe() creates a second pipe that is never drained. If tailscale status --json writes more than ~64KB to stderr, the child blocks on the stderr pipe write while the parent blocks on readDataToEndOfFile() for stdout — the same deadlock this PR set out to fix.

Redirect stderr to nullDevice instead, matching the pattern in childPIDs(of:) in AutomationExecutor.swift (line 732).

🔧 Proposed fix
-        process.standardError = Pipe()
+        process.standardError = FileHandle.nullDevice
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@XboxControllerMapper/XboxControllerMapper/Services/Input/UniversalControlMouseRelay.swift`
around lines 1400 - 1410, The `tailscale status --json` launch in
`UniversalControlMouseRelay` still creates an unread `standardError` pipe, which
can deadlock the process when stderr fills up. Update the `process.run()` setup
to redirect `standardError` to `FileHandle.nullDevice` instead of `Pipe()`,
following the same pattern used by `childPIDs(of:)` in `AutomationExecutor`,
while leaving the stdout read path unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In
`@XboxControllerMapper/XboxControllerMapper/Services/Input/UniversalControlMouseRelay.swift`:
- Around line 1400-1410: The `tailscale status --json` launch in
`UniversalControlMouseRelay` still creates an unread `standardError` pipe, which
can deadlock the process when stderr fills up. Update the `process.run()` setup
to redirect `standardError` to `FileHandle.nullDevice` instead of `Pipe()`,
following the same pattern used by `childPIDs(of:)` in `AutomationExecutor`,
while leaving the stdout read path unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 64ae31d6-360a-470a-9667-73e6e670a63a

📥 Commits

Reviewing files that changed from the base of the PR and between c431981 and 2b9011c.

📒 Files selected for processing (3)
  • .Jules/sentinel.md
  • TriggerKit/Sources/TriggerKitRuntime/AutomationExecutor.swift
  • XboxControllerMapper/XboxControllerMapper/Services/Input/UniversalControlMouseRelay.swift

google-labs-jules Bot and others added 2 commits July 8, 2026 09:26
Co-authored-by: NSEvent <44446865+NSEvent@users.noreply.github.com>
Co-authored-by: NSEvent <44446865+NSEvent@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant