Skip to content

Fix RPC framework errors caused by concurrent visitor cursor access#6880

Merged
knutwannheden merged 5 commits intomainfrom
investigate-rpc-framework-errors
Mar 5, 2026
Merged

Fix RPC framework errors caused by concurrent visitor cursor access#6880
knutwannheden merged 5 commits intomainfrom
investigate-rpc-framework-errors

Conversation

@knutwannheden
Copy link
Contributor

@knutwannheden knutwannheden commented Mar 5, 2026

Summary

  • Clean up remoteObjects in GetObject.Handler catch block to prevent stale baseline on retry after send failure
  • Create new sender/receiver instances per RPC codec call in DynamicDispatchRpcCodec subclasses, eliminating thread-safety issues from shared mutable visitor state

Test plan

  • gw :rewrite-core:test --tests "org.openrewrite.rpc.RewriteRpcTest" — tests for remoteObjects cleanup on send failure and baseline reuse

Two fixes for errors seen in production recipe runs against JS/TS repos:

1. TreeVisitor.visit(): Use local variables for cursor management instead
   of reading from the mutable `cursor` field, which can be clobbered when
   singleton sender visitors are shared across ForkJoinPool threads. The
   field writes via setCursor() are preserved so getCursor() in visitor
   methods still works.

2. GetObject.Handler: Remove stale remoteObjects entry on send failure, so
   the next getObject() call sends a full ADD instead of a CHANGE delta
   against a partially-sent baseline.
@github-project-automation github-project-automation bot moved this to In Progress in OpenRewrite Mar 5, 2026
@knutwannheden knutwannheden added the bug Something isn't working label Mar 5, 2026
DynamicDispatchRpcCodec subclasses are singletons (loaded via
ServiceLoader), but previously some held singleton sender/receiver
visitor fields with mutable cursor state. Under concurrent access
from GetObject.Handler's ForkJoinPool, this caused NPEs.

Create new sender/receiver instances per rpcSend/rpcReceive call,
matching the pattern already used by Python, JavaScript, and C# codecs.
…types

The parameterizedSignature() method added to the cycle-detection stack but
never checked the return value, so revisiting the same Parameterized through
MultiCatch or Intersection types caused infinite recursion.

- Check parameterizedStack.add() return value and short-circuit on cycle
- Use try/finally to ensure stack cleanup even on exceptions
- Add cycle protection to multiCatchSignature() and intersectionSignature()
- Add tests for cyclic Parameterized→MultiCatch and self-referencing types
@knutwannheden knutwannheden merged commit 68d913c into main Mar 5, 2026
1 check passed
@knutwannheden knutwannheden deleted the investigate-rpc-framework-errors branch March 5, 2026 15:05
@github-project-automation github-project-automation bot moved this from In Progress to Done in OpenRewrite Mar 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant