fix: trap with 'Call already trapped' when using futures::stream #450
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 MR fixes the following issue with polling multiple futures using
futures::stream
: when invoking the methodbar
of the following canister codethe call fails with "Canister did not reply to the call" instead of the expected "Call already trapped".
This is the root cause I believe. Since the current context's waker (a.k.a. cdk-rs' waker) is replaced by another one, the new waker will be invoked here or here and then the new waker will wake the cdk-rs' waker (see here). Afterwards, it's the cdk-rs' waker responsibility to poll again. However, we don't want to poll again after a trap and thus the cdk-rs' waker will never be woken again after a trap and thus we won't keep trapping for subsequent callbacks. Consequently, the overall update call will fail with with "Canister did not reply to the call" instead of "Call already trapped". Moreover, the state of the outstanding futures will be dropped after the cleanup callback of the trapped future (since we won't poll the parent update call's future) and thus we can trap with "Call already trapped" if we don't find the call future's state in the callback handler which is exactly what this PR implements.