Conversation
This is purely moving code into a new private method. No changes were made to the code.
This avoids the need to check the `weakIoContext` in `JsRpcTargetBase::call()` before calling the callback, which is nice because the callback already holds its own weak ref and does its own check.
This can be completely handled by the re-entry callback now.
Since we're no longer using the hack where `callImpl()` runs as part of a `ctx.addTask()`, it's now the case that the promise returned by `callImpl` will be canceled if the incoming RPC is canceled. The whole reason to hold onto `thisCap` is because if the RPC was canceled, then the RPC server could subsequently be dropped, but the addTask()ed callImpl() could still be running, so it needed to make sure `this` didn't disappear under it. But now the body of `callImpl()` will actually be canceled, so it doesn't matter if `this` goes away. We still do need `ownCallContext`, but we can acquire it later than we did before, inside the body of `callImpl()` -- because if the call is canceled before that, we won't get to this point anyway.
`makeReentryCallback()`, as its name implies, is for *re-*entry, not original entry. In particular, the callback itself holds a PendingEvent. This does not make sense at the top level, as it would mean there is always a PendingEvent, breaking the whole mechanism for RPC events. (I've added a test which was broken by this.) It turns out, for the top-level call, we don't really need the complexity of `makeReentryCallback()` anyway. We can arrange to ensure that EntrypointJsRpcTarget cannot outlive the IoContext / IncomingRequest, then just use ctx.run() like normal.
Since the re-entry callback already holds one.
The error messages aren't ideal, but I'm going to punt that for now. The behavior otherwise seems fine.
This forces a test failure in an internal test that triggers this behavior -- or at least it did, before the changes in this PR fixed the problem (since we no longer use addTask() for individual RPCs). That said, the deeper bug isn't really fixed, which is that abort handling is extremely messy and does not actually cancel all outstanding tasks. That will require more work.
9e15075 to
a848aec
Compare
ObsidianMinor
approved these changes
May 18, 2025
anonrig
approved these changes
May 19, 2025
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This introduces
IoContext::makeReentryCallback(), which takes a function intended to run under the isolate lock, and returns a function which can be invoked outside the lock, and which will do all the necessary things to enter the isolate. This has proven more complicated than it looks. See the doc comment for details.I created this for a different use case, but in this PR I went ahead and used it to clean up how JsRpcTarget works, as I was fairly unhappy with the existing code.
This fixes at least one bug with RPC: If you made an RPC call during blockConcurrentlyWhile, and passed it a callback, calls to the callback would be blocked until the end of blockConcurrencyWhile. This goes against the usual semantics of blockConcurrencyWhile, which says that interactions initiated from inside the block are allowed to complete inside the block.
This PR also fixes the warning
Adding task to IoContext with no current IncomingRequest, but sort of by accident, and there are deeper underlying problems there which aren't actually fixed. I might work on that in a separate PR.