-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Domain.DLS
is not thread-safe
#12677
Comments
@polytypic The issue isn't fixed yet. Unsure whether the issue has been accidentally closed. |
I would like to see progress on #12724, but this is at best for 5.3. I think that there is a real bug here that we could fix for 5.2, and I will look at it -- this is related to some of the thread-safety musings I had with Dynarray. |
I implemented a candidate fix for 5.2 in #12889, but this is not tested to fix the problem. (The current issue does not contain a repro case that I could run on my branch.) |
The current
Domain.DLS
implementation is not (sys)thread-safe, because the implementations of the various state updating operations include safe points during which the runtime may switch between threads. I'll briefly highlight some specific scenarios of what can go wrong.Consider the implementation of
Domain.DLS.get
:ocaml/stdlib/domain.ml
Lines 120 to 127 in e397ed2
Two threads on a single domain that concurrently
get
with the same key beforeinit
has been called may both end up callinginit
(soinit
would be called twice for a single key). That can happen becausemaybe_grow
(which potentially allocates) includes a safe point and becauseinit
(which often allocates) itself may include a safe point. What can happen then is that the two calls ofget
return two different results (e.g. two different mutable records), one of which is stored in DLS.Consider the implementation of the internal
Domain.DLS.maybe_grow
:ocaml/stdlib/domain.ml
Lines 98 to 111 in e397ed2
Two threads on a single domain that concurrently
get
with two different keys both callmaybe_grow
and may both end up allocating a new array for the DLS. This is possible becausemaybe_grow
includes a safe point. Only one of the two arrays eventually ends up being stored as the DLS and one of theget
operations ends up being undone. Furthermore if the two threads also performset
operations, some of those may end up being undone.Here is an example interleaving (variation of the above) where the effects of
DLS
operations performed by Thread B vanish:The effects of both
get y
andset y
vanish. Even just havingget y
vanish is a problem, becauseget
may callinit
, which may return a mutable object, which might be mutated or stored outside of the DLS.The text was updated successfully, but these errors were encountered: