-
Notifications
You must be signed in to change notification settings - Fork 177
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
Npick fix #447
Npick fix #447
Conversation
From my understanding, the build checks fail because of these tests in ./test/core/test_lwt.ml: (* The behavior of [p] tested here is a current bug in [Lwt.npick]. *) (* This is the same bug as above. *) These tests were testing for buggy behavior that is now fixed. |
New commit that moves the cancellation of promises to after some of them have the chance to complete. |
Huh, the build produced an unable to install parsetree error. That shouldn't be related to the changes I made. |
Indeed it's not, see ocaml-ppx/ocaml-migrate-parsetree#19 (comment). We can just ignore that build row for now; I'll list in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, it's pretty much correct, but I'm asking for a change due to a pure subtlety. Sorry that things like that matter in Lwt. This is a learning process for me too...
src/core/lwt.ml
Outdated
let State_may_have_changed p = | ||
finish_nchoose_or_npick_after_pending in_completion_loop p [] ps in | ||
List.iter cancel ps; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe this reordering produces the correct behavior.
There is one weird thing about Lwt now, though:
- The callback of
Lwt.pick
cancels the pending promises before completing its own ("final") promise. - This modified callback of
Lwt.npick
cancels the pending promises after completing its own promise.
This means that code running in on_cancel
and regular callbacks of the respective pending promises can observe different states of the final promise depending on which function is used. Likewise, code running in the callbacks of the final promises can observe different states of the (to-be) canceled promises, depending on which function is used.
I'm not sure if that's really a problem, since we don't document or guarantee either behavior, and I'm not aware of any pathological interactions due to picking one or the other, so one could argue that this doesn't need to be addressed right now.
However, it could cause problems for users refactoring their code. For completeness, this could be addressed by factoring out the implicit final promise completion from finish_nchoose_or_npick_after_pending
, so that function only collects the result, and the callback can fully control the order of (1) figuring out the result (2) canceling the pending promises (3) setting the state of the final promise (the one returned by npick
itself). Callbacks in both npick
and nchoose
will have to be modified to call complete
explicitly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A secondary reason to prefer the ordering in pick
is that function gets used a lot, so presumably that behavior is not problematic.
@@ -2361,7 +2374,7 @@ let npick_tests = [ | |||
Lwt.state p = Lwt.Fail Lwt.Canceled) | |||
end; | |||
|
|||
(* This is the same bug as above. *) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is fine, but FYI OCaml supports nested comments, so this can be reverted.
test/core/test_lwt.ml
Outdated
Lwt.return (Lwt.state p3 = Lwt.Return [()]) | ||
(* Actual: *) | ||
(*Lwt.return (Lwt.state p3 = Lwt.Fail Lwt.Canceled)*) | ||
end; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for inserting this here!
@ZackC I wrote a small program to show the two behaviors, in part for my own education, but it may also be helpful for ensuring same ordering: https://gist.github.com/aantron/4db12b8e5ca92f57f7a223e594c833cc |
…nge to cancel the other promises
Thanks for fixing this! |
No problem. Glad to help! |
#340 - removed the line that causes a list of pending promises to be canceled.