Skip to content

[Bug]: pi-fff external-path grep can permanently block the Pi process #843

Description

@felixkang

Frontend

Other / multiple — @ff-labs/pi-fff using @ff-labs/fff-node.

Environment

  • @ff-labs/pi-fff: reproduced from the 0.10.5 code path; the relevant external-finder path still appears present in 0.10.6
  • Pi: 0.84.4
  • Node: 26.0.0
  • macOS 27.0

Reproduction

Run an external absolute-path grep against a package under an otherwise broad indexed tree:

ffgrep /allowRanges/ in ~/.pi/agent/npm/node_modules/pi-web-access/ limit 20

Intermittently, Pi remains on Working... indefinitely. The tool-level 10-second grep budget and the auxiliary finder startup timeout do not recover the process.

The target itself is small and the same search normally completes quickly, so this is not simply a slow full-tree scan.

Expected behavior

The search should return matches, No matches found, or a bounded actionable timeout without blocking Pi's main JavaScript thread.

Actual behavior

A synchronous native create/index/grep call can stop returning. Because the event loop is blocked inside FFI, an outer Promise.race/timer cannot fire and the whole Pi process remains stuck.

Investigation

Instrumentation of the pi-fff auxiliary finder lifecycle showed this sequence in the reproduced case:

  1. A broader auxiliary finder exceeded its scan/startup wait.
  2. Native scan/warmup continued after the JavaScript-side wait timed out.
  3. The finder remained reusable while the global creation queue was released.
  4. A later external-root grep entered native FFI while the earlier native work was still active.
  5. Once the synchronous FFI call stopped returning, the JavaScript timeout could not interrupt it.

There may also be an interaction with:

Those fixes improve routing/budget behavior, but a JavaScript timer still cannot terminate a native synchronous call that has already wedged.

Locally verified mitigation

As a local diagnostic/fix, we moved external-path grep only behind a bounded child-process lifecycle:

  • exact-root workers
  • same-root startup deduplication
  • serialized native finder creation across roots
  • bounded hot-worker pool
  • startup/request/abort/shutdown all terminate the child process when necessary
  • workspace grep and fffind remain unchanged

Regression coverage includes cold/hot search, matches and zero matches, explicit node_modules roots, startup timeout, grep timeout, abort, concurrent roots, and recovery after termination.

With that isolation, the original target returns 38 matches in about 1.6 seconds, and a deliberately wedged native worker can be killed without freezing Pi.

I am filing the issue first because the preferred upstream fix may be either:

  1. native cancellation/time-budget enforcement in the SDK/Rust owner, or
  2. process/thread isolation in pi-fff for external-path operations.

I can submit the isolated pi-fff implementation if that direction is useful.

Logs

No useful log is emitted once the synchronous FFI call blocks; the JavaScript process cannot progress far enough to report the timeout.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions