New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: lazy CallFuture #391
fix: lazy CallFuture #391
Conversation
This is a reversion of an intentionally implemented feature - users who want lazy execution given eager execution can wrap in an |
@adamspofford-dfinity I see your point. On the other hand, the example I've now included in the Motivation section results in a rather unexpected behavior and it's not clear to me if it can't be exploited for code obfuscation. Could you please take a look? |
@adamspofford-dfinity this PR is one (out of at least two) possible way of dealing with the unexpected behavior, so we may choose to resolve it in a different way. But don't you agree that this is an issue that should be resolved? The fact that |
Ah, I hadn't known this was an issue (the original comment didn't have the explanation @Dfinity-Bjoern), and also looking closer, the original purpose of this behavior has been superseded by |
* Allow argument data to be borrowed * have these been non-extern fns the entire time?
Description
This PR updates the semantics of
CallFuture
to only make the inter-canister call (callingic0::call_new
, ...,ic0::call_perform
) when the future is actually awaited. In particular, if the future is never awaited, then the inter-canister call is not performed at all. Otherwise, firing the call is postponed to the code location that awaits the future.Motivation
Given the current semantics of
CallFuture
, it is possible that the inter-canister call is fired from a call context C that creates the future while the future is only awaited in another call context D. Depending on the actual message scheduling, this leads to one of the following scenarios:We can exemplify the unexpected case with the code snippet below (thanks to @crusso ):
Here a future stored in
CELL
is created in the call context ofwriter
(call context C in the description above) and awaited in the call context ofreader
(call context D in the description above). Calling the methodgo
on a local replica results in the unexpected case of the method reader (called fromgo
) producing no response because its call context (D) didn't reply while the methodwriter
(call context C) returns 666 (instead of 42 suggested by the code ofwriter
) because the continuation after the await point in the methodreader
was executed in the call context ofwriter
(C) and returned 666. The debug output produced by a local replica for the above canister code reads:Checklist: