-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
RFC: yield after require
#43339
RFC: yield after require
#43339
Conversation
Under specific circumstances (package callbacks that run under `@async`), this can change the ordering of operations: some may miss a `yield` window due to locking. This adds a `yield` when the lock is freed.
I can fix the test error by changing |
Just to clarify, this isn't technically unique to Revise, right? Any package that adds package callbacks will be susceptible to this bug if the callbacks are run under In my opinion, it would make the most sense to fix this in a single place (i.e. in Base Julia), instead of having to fix it in multiple places (i.e. in every package that uses package callbacks). |
Calling |
I basically agree, and mostly wanted to document the issue in case anyone else is affected. I'll fix it in Revise. |
We could definitely unlock though, since it is undefined right now if you are allowed to do anything |
I'll play with that tomorrow-ish and see what comes of that. |
Actually, unlocking won't really make a difference for Revise, since Revise would rather do as much of the work asynchronously as possible. So by the time Revise gets a crack at it, the lock may be applied again. |
Seems that this callback is already causing deadlocks with the presence of the Distributed._require_callback, so we need to fix it. In particular:
|
Under specific circumstances (package callbacks that run under
@async
), this can change the ordering of operations:some may miss a
yield
window due to locking. This addsa
yield
when the lock is freed.It's worth showing how this new
@testset
behaves under Julia 1.6 and current nightly (see the diff for explanation). This comparison is done adding ayield()
after the@eval using Outer41602
. For Julia 1.6,@show cti cto
yieldsimplying that
Inner
's callback runs first for bothInner
andOuter
(in that order). On current nightly, one getsimplying that
Inner
's callback runs first forOuter
, followed byOuter
's callback, and much later byInner
's callback for itself. Presumably, this occurs because when it initially tries to run its own callback,Base.require_lock
is still being held forOuter
, and hence it blocks the callback until the nextyield
. This PR restores the original ordering.As mentioned in #41602 (comment), #41602 triggered failures in Revise. There's an alternative way to fix this in Revise itself, by getting rid of one or two forms of asynchronous processing. The one that must go is the asynchronous processing of the
@require
blocks; this is the first commit in timholy/Revise.jl#657. The one that's optional is the asynchronous handling ofwatch_package
: it would be nice to leave that one asynchronous because it defers Revise's work until after Julia returns to the REPL. If we drop that commit, I can manually add ayield()
in a couple of places in Revise's tests.In other words, we don't have to change anything in Base (in which case this can be closed) if it's viewed as better being fixed in Revise: perhaps the ideal fix is to not make this change, take only the first commit of timholy/Revise.jl#657, and add a couple of
yield
s in Revise's own tests. But, having finally understood where the breakage came from, I thought it was worth explaining the consequences of recent changes in case this proves to be the kind of breakage we want to avoid.