Description
I have a custom collection implementation which relies on IEnumerator<T>.Dispose being called in order to release a read lock, however I discovered that on serialization System.Text.Json will grab the IEnumerator<T> but does not appear to call Dispose which results in my custom collection being in a permanent ReadLocked state.
I've just switched from Newtonsoft.Json which doesn't have this issue.
Example Code: https://gist.github.com/LXGaming/862f498de548c67d0ed7d193d22d2499
Configuration
- Which version of .NET is the code running on? .NET 5
- What OS and version, and what distro if applicable? Windows 10 20H2, dotnet/runtime:5.0 Docker Image on Ubuntu 20.04
- What is the architecture (x64, x86, ARM, ARM64)? x64
- Do you know whether it is specific to that configuration? I don't believe so.
- If you're using Blazor, which web browser(s) do you see this issue in? N/A
Regression?
I don't know.
Other information
This issue can be worked around by creating a custom converter for the custom collection.
This issue is also present in several other Converters, The IEnumerator<T> is obtained in OnWriteResume
|
protected override bool OnWriteResume( |
|
Utf8JsonWriter writer, |
|
TCollection value, |
|
JsonSerializerOptions options, |
|
ref WriteStack state) |
|
{ |
|
IEnumerator<TElement> enumerator; |
|
if (state.Current.CollectionEnumerator == null) |
|
{ |
|
enumerator = value.GetEnumerator(); |
|
if (!enumerator.MoveNext()) |
|
{ |
|
return true; |
|
} |
|
} |
|
else |
|
{ |
|
enumerator = (IEnumerator<TElement>)state.Current.CollectionEnumerator; |
|
} |
|
|
|
JsonConverter<TElement> converter = GetElementConverter(ref state); |
|
do |
|
{ |
|
if (ShouldFlush(writer, ref state)) |
|
{ |
|
state.Current.CollectionEnumerator = enumerator; |
|
return false; |
|
} |
|
|
|
TElement element = enumerator.Current; |
|
if (!converter.TryWrite(writer, element, options, ref state)) |
|
{ |
|
state.Current.CollectionEnumerator = enumerator; |
|
return false; |
|
} |
|
} while (enumerator.MoveNext()); |
|
|
|
return true; |
|
} |
Description
I have a custom collection implementation which relies on
IEnumerator<T>.Disposebeing called in order to release a read lock, however I discovered that on serialization System.Text.Json will grab theIEnumerator<T>but does not appear to callDisposewhich results in my custom collection being in a permanent ReadLocked state.I've just switched from Newtonsoft.Json which doesn't have this issue.
Example Code: https://gist.github.com/LXGaming/862f498de548c67d0ed7d193d22d2499
Configuration
Regression?
I don't know.
Other information
This issue can be worked around by creating a custom converter for the custom collection.
This issue is also present in several other Converters, The
IEnumerator<T>is obtained inOnWriteResumeruntime/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/ICollectionOfTConverter.cs
Lines 56 to 94 in 7360c19