List of possible race conditions - acrylic-origami/HHReactor GitHub Wiki
What Hack doesn't guarantee
The Hack langspec on async functions unfortunately doesn't make many guarantees about async behavior, which opens up the possibility of race conditions that may be virtually impossible in practice but are possible by the spec. The most significant fallout is on ordering between events in parallel coroutines, which is understandable from a specification standpoint, but in many cases produces very unintuitive and surprising behavior. Below are the most relevant specifications (as of HHVM 3.19):
return
ing from an async function or block could throw control to any pendingAwaitable
(although it "typically" returns control to the caller). Spec- When control hits an
await
statement, control could be given to resume the async function that produced theAwaitable
if it is resumable. Because of 1., this means that if that function happens to thenreturn
s synchronously, control could go anywhere. Spec
Generally, when multiple resumable await
statements are queued in parallel in the scheduler, there are no guarantees which will get control next; there is no dependence on which resolved first or last. This is "deliberately not specified".
Whether or not ConditionWaitHandle::{succeed, fail}
will give control back to the calling scope immediately isn't specified in the langspec either. Anecdotally, it has never happened in testing so far, but without specification this could be subject to change unpredictably in the future [right?].
Assumptions
To actually do anything interesting with reasonable simplicity, the HHReactor implementation has had to rely on the following assumptions in limited places:
- If control does go to the async function after an
await
statement and the async functionreturn
s, control always returns to the calling scope. ConditionWaitHandle::{succeed, fail}
gives control back to the calling scope immediately, as though they are synchronous function calls.