He-Pin opened a new pull request, #3086: URL: https://github.com/apache/pekko/pull/3086
### Motivation When `context.cancelReceiveTimeout()` is called while a classic `ReceiveTimeout` message has already been enqueued in the mailbox by the scheduler, the typed actor crashes with a `NullPointerException` inside `InterceptorImpl.receive`. **Root cause trace:** 1. `setReceiveTimeout(d, msg)` → sets `receiveTimeoutMsg = msg`, schedules `classic.ReceiveTimeout` via `scheduleOnce` 2. Before the actor processes the enqueued `ReceiveTimeout`, another message triggers `cancelReceiveTimeout()` 3. `cancelReceiveTimeout()` sets `receiveTimeoutMsg = null` and calls `classicActorContext.setReceiveTimeout(Duration.Undefined)` 4. The already-enqueued `classic.ReceiveTimeout` **cannot be retracted** from the mailbox (the `Cancellable.cancel()` only prevents future scheduling, not already-delivered messages) 5. `ActorAdapter.aroundReceive` matches `classic.ReceiveTimeout` and calls `handleMessage(ctx.receiveTimeoutMsg)` — **with null** 6. The null message propagates through `Behavior.interpretMessage` → `InterceptorImpl.receive` → **`msg.getClass` throws NPE** This bug was observed in both 2.8.3 and 2.6.21 of the upstream project. A reproduction is available at https://github.com/lolboxen/akka-receive-timeout-bug. ### Modification - `ActorAdapter.aroundReceive`: null-check `ctx.receiveTimeoutMsg` before forwarding to `handleMessage`. If null (timeout was cancelled), the stale `classic.ReceiveTimeout` is silently discarded. - Added `CancelReceiveTimeoutSpec`: a deterministic regression test that directly sends `classic.ReceiveTimeout` to a typed actor after `cancelReceiveTimeout()` has been called, verifying the actor survives without NPE. The test uses an interceptor in the behavior stack to exercise the exact `InterceptorImpl.receive` code path where the NPE manifests. ### Result Typed actors no longer crash when `cancelReceiveTimeout()` races with an already-enqueued stale `ReceiveTimeout`. The fix is a single null-guard at the adapter layer — the typed behavior stack never sees a null message. ### Tests ``` sbt "actor-typed-tests / Test / testOnly org.apache.pekko.actor.typed.CancelReceiveTimeoutSpec" → All tests passed sbt "actor-typed-tests / Test / testOnly org.apache.pekko.actor.typed.ActorContextSpec org.apache.pekko.actor.typed.TimerSpec org.apache.pekko.actor.typed.CancelReceiveTimeoutSpec" → 14 tests passed, 0 failed ``` The regression test was verified to **fail without the fix** (NPE at `InterceptorImpl.scala:94`) and **pass with the fix**. ### References - Reproduction: https://github.com/lolboxen/akka-receive-timeout-bug -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected] --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
