Skip to content
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

Please add documentation for thread-safety guarantees of JsonDocument (and related types) #20563

Closed
dpaoliello opened this issue Sep 8, 2020 · 8 comments · Fixed by #24938 or #31508
Closed
Assignees
Labels
doc-enhancement Improve the current content [org][type][category] dotnet/svc Pri2

Comments

@dpaoliello
Copy link

dpaoliello commented Sep 8, 2020

Description

Looking at the documentation for JsonDocument it is not obvious if it can be safely used by multiple threads or not.

A cursory glance at the code suggests that the parsing is done up-front and, therefore, it is safe - however we tripped over the caching that is done via _lastIndexAndString (i.e., if multiple threads call GetString on an element at the same time, then they may get back the wrong value).

I want to be clear that this is a doc bug: I'm fine with having a string cache (since I assume that it provides noticeable perf benefits), but I would have liked clear guidance that JsonDocument and uses of any JsonElement from the same parent document cannot be done safely from multiple threads (without calling Clone on each element).


Document Details

Do not edit this section. It is required for docs.microsoft.com ➟ GitHub issue linking.

@layomia layomia transferred this issue from dotnet/runtime Sep 10, 2020
@dotnet-bot dotnet-bot added the ⌚ Not Triaged Not triaged label Sep 10, 2020
@layomia
Copy link
Contributor

layomia commented Sep 10, 2020

FYI @tdykstra - hope to address this in the .NET 5 doc wave for JSON.

@kstittleburg
Copy link

kstittleburg commented Sep 24, 2022

I don't think documentation was adequately updated for this issue, ran into this in some code at my day job. With the fix PR (#24938) it now explicitly states JsonDocument is thread-safe and only mentions cloning in the context of object disposal, when the original issue is that JsonDocument (and by extension JsonElement or JsonProperty that utilize JsonDocument) are not thread safe (edit: or at least my definition of what thread-safe means) due to _lastIndexAndString caching.

@adj123
Copy link

adj123 commented Sep 29, 2022

Seconded, please amend this. I also just wasted days tracing a sporadic concurrency bug in my application code down to an immutable BCL type which is documented as thread-safe.

@tdykstra tdykstra reopened this Sep 29, 2022
@tdykstra
Copy link
Contributor

@eiriktsarpalis @gewarren Please see the latest two comments on this issue.

@gewarren gewarren assigned gewarren and unassigned tdykstra Sep 29, 2022
@eiriktsarpalis
Copy link
Member

eiriktsarpalis commented Sep 30, 2022

however we tripped over the caching that is done via _lastIndexAndString (i.e., if multiple threads call GetString on an element at the same time, then they may get back the wrong value).

Looking at the code, I would guess that this can only happen because of torn reads/writes. It might be that we could fix this in the code using a regular System.Tuple, thus ensuring atomic access to cached entries. Obviously this has the downside of incurring one additional allocation, but at least we can guarantee immutability (modulo disposability of course).

Related to dotnet/runtime#17975

cc @layomia @krwq

@eiriktsarpalis
Copy link
Member

We probably don't want to sacrifice performance (added allocations) for thread safety, so until we have atomic APIs for 128-bit data we should probably just document that the type is not thread safe.

@ghost ghost added the in-pr This issue will be closed (fixed) by an active pull request. label Sep 30, 2022
@ghost ghost removed the in-pr This issue will be closed (fixed) by an active pull request. label Sep 30, 2022
@adj123
Copy link

adj123 commented Sep 30, 2022

Thanks for looking at this so speedily after our revival of this issue. I'm not sure without further clarification of your intent that it can be said to be closed though, as the PR only removes the mention of thread safety without explicitly stating that it is not thread safe, and thus we're just back to the same situation we were in when this issue was first raised - the OP requested:

but I would have liked clear guidance that JsonDocument and uses of any JsonElement from the same parent document cannot be done safely from multiple threads (without calling Clone on each element).

@eiriktsarpalis
Copy link
Member

Copying my response from the latest PR:

For all intents and purposes the design of JsonDocument was to provide an immutable and thus thread-safe DOM representation for JSON values. What impacts thread safety is in fact a concurrency bug impacting specific methods of the API that we should be fixing (and potentially servicing in older releases).

I'm not sure how to best express this in documentation other noting it as a known bug.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
doc-enhancement Improve the current content [org][type][category] dotnet/svc Pri2
Projects
None yet
Development

Successfully merging a pull request may close this issue.

10 participants