Skip to content

macOS fs_usage is a single global sensor — two agents on one host knock each other's watcher out #94

Description

@LiorFink00

Summary

On macOS, fs_usage reads the kernel trace facility (kdebug), which is effectively a single global, single-consumer resource (shared with dtrace, latency, sc_usage). When two Thumper agents run on the same host and both take the fs_usage path in watch_fs_usage, only one can hold the trace. The agent that starts fs_usage last wins, and the earlier agent's fs_usage is terminated — silently disabling its read detection.

Evidence (observed live)

Two agents on one Mac, both root, byte-identical thumper_agent.sh:

  • thumper-demo (/usr/local/thumper) — started 11:17 — has a live fs_usage:
    99418  fs_usage -w -f filesys     (child of thumper-demo watcher)
    
  • thumper-dev (/usr/local/thumper-2) — started 11:16, logged watching 1 bait file(s) via fs_usage — has no fs_usage, no grep, no watcher subshell left. Its watcher pipeline collapsed when demo's fs_usage took over the trace.

System-wide there is exactly one fs_usage process, belonging to the agent that started last.

Where

  • agent/thumper_agent.sh:437 watch_fs_usage() — runs fs_usage … | grep … | while read
  • agent/thumper_agent.sh:521 start_watcher() — chooses fs_usage on darwin+root

Impact

A host with two enrolled installs silently loses read detection on one of them. The bait still exists; a read of it goes undetected. High severity because read detection is the entire product.

Proposed direction

  • Detect that fs_usage failed to acquire / lost the trace (pipeline EOF immediately after start) and surface it loudly (see the "watcher dies with no log" issue).
  • Coordinate a single shared fs_usage sensor per host that fans out to all local installs, OR
  • Fall back to the atime poll for the loser instead of going blind, OR
  • At minimum, refuse/warn when a second agent on the same host would contend for fs_usage (see the "double agent on one host" issue).

Related: double-agent host guard, watcher-dies-silently, heartbeat-false-healthy, dead-watcher-not-restarted.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions