Skip to content

fix(intercept): embedded interceptStatus() caches the FFI start and goes stale when the shared slot changes via the admin plane - #317

Merged
EtaCassiopeia merged 1 commit into
masterfrom
fix/rift-301-intercept-status-shared-slot
Oct 16, 2026
Merged

EtaCassiopeia merged 1 commit into
masterfrom
fix/rift-301-intercept-status-shared-slot

Conversation

@EtaCassiopeia

Copy link
Copy Markdown
Collaborator

On the embedded transport, interceptStatus() cached the result of the FFI rift_start_intercept, and only this handle's own stopIntercept() cleared it. The C-ABI and the embedded admin plane share one InterceptControl slot (rift#521, confirmed by the rift#1351 triage). So once another client stopped or restarted the listener through the plane, the cached status was stale:

  • after a DELETE /intercept on the plane, the handle kept reporting the dead port;
  • after a new POST /intercept, it reported the old port.

Changes

  • EmbeddedTransport.interceptStatus() reads the admin plane's GET /intercept whenever a plane is served. It uses the cached FFI start only when no plane exists, since nothing else can change the slot then. Asking does not start the plane.
  • RiftImpl.intercept(InterceptOptions.attach()) therefore no longer attaches to a dead port after a plane-side stop.
  • Docs: the Rift.interceptStatus() javadoc, docs/intercept.md and docs/design/sdk-api.md drop the incorrect "two sources" description.

Tests (InterceptE2eIT)

  • anFfiStartedListenerStoppedThroughTheAdminPlaneIsNoLongerReported: an FFI start, then DELETE /intercept on the plane (204), and the status is empty.
  • aListenerRestartedThroughTheAdminPlaneIsReportedWithItsNewPort: after the plane-side stop, another client restarts the listener, and the status shows the new port.
  • anFfiStartAfterTheAdminPlaneIsServedIsReported: a regression pin for this handle's own start once a plane is served. It passed before the fix and is kept on purpose.

Before the fix, the first two failed with stale ports (expected: <55730> but was: <55727>; expected: <Optional.empty> but was: <Optional[InterceptStatus[port=55744 …]]>).

Verification

RIFT_IT=1 ./mvnw -B -fae verify on JDK 21, against the rift 0.22.0 corpus, dylib and binary: green. All 19 InterceptE2eIT tests pass.

Follow-up

A related finding was filed as #316: after a plane-side stop, the handle's own intercept() still refuses with "already started".

Closes #301

🤖 Generated with Claude Code

…e once one is served

The C-ABI and the embedded admin plane share one intercept slot (rift#521),
so the plane's GET /intercept already reports an FFI-started listener. The
cached FFI start went stale as soon as another client stopped or restarted
the listener through the plane. The plane now answers whenever it is served;
the cached start answers only when no plane exists, since then nothing else
can change the slot. Asking still never starts the plane.

Closes #301
@EtaCassiopeia
EtaCassiopeia merged commit 8dcd777 into master Oct 16, 2026
33 of 34 checks passed
@EtaCassiopeia
EtaCassiopeia deleted the fix/rift-301-intercept-status-shared-slot branch October 16, 2026 20:48
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.

fix(intercept): embedded interceptStatus() caches the FFI start and goes stale when the shared slot changes via the admin plane

1 participant