Skip to content

Commit

Permalink
TINKERPOP-2976 Fix modification while iterating
Browse files Browse the repository at this point in the history
In rare cases users could get an InvalidOperationException if the
dictionary of `_serializerByType` was modified while another thread in
parallel iterated over the keys of this dictionary.
Just creating a copy of the supported types and then iterating over that
should fix this.
The problem was reported for GraphBinary, but the GraphSONWriter had the
same problem so I also fixed it there.
  • Loading branch information
FlorianHockmann committed Aug 9, 2023
1 parent 008f9da commit eda4ea6
Show file tree
Hide file tree
Showing 3 changed files with 14 additions and 13 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
[[release-3-5-8]]
=== TinkerPop 3.5.8 (NOT OFFICIALLY RELEASED YET)
* Fixed a bug in Gremlin.Net that can lead to an `InvalidOperationException` due to modifying a collection while iterating over it in the serializers.
[[release-3-5-7]]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,11 +159,11 @@ private TypeSerializerRegistry(List<CustomTypeRegistryEntry> customTypeEntries)
/// <exception cref="InvalidOperationException">Thrown when no serializer can be found for the type.</exception>
public ITypeSerializer GetSerializerFor(Type valueType)
{
if (_serializerByType.ContainsKey(valueType))
if (_serializerByType.TryGetValue(valueType, out var serializerForType))
{
return _serializerByType[valueType];
return serializerForType;
}

if (IsDictionaryType(valueType, out var dictKeyType, out var dictValueType))
{
var serializerType = typeof(MapSerializer<,>).MakeGenericType(dictKeyType, dictValueType);
Expand Down Expand Up @@ -199,7 +199,7 @@ public ITypeSerializer GetSerializerFor(Type valueType)
return serializer;
}

foreach (var supportedType in _serializerByType.Keys)
foreach (var supportedType in new List<Type>(_serializerByType.Keys))
{
if (supportedType.IsAssignableFrom(valueType))
{
Expand Down Expand Up @@ -245,7 +245,7 @@ private static bool IsListType(Type type)
implementedInterface.GetGenericTypeDefinition() ==
typeof(IList<>));
}

/// <summary>
/// Gets a serializer for the given GraphBinary type.
/// </summary>
Expand All @@ -255,10 +255,10 @@ public ITypeSerializer GetSerializerFor(DataType type)
{
if (type == DataType.Custom)
throw new ArgumentException("Custom type serializers can not be retrieved using this method");

return _serializerByDataType[type];
}

/// <summary>
/// Gets a serializer for the given custom type name.
/// </summary>
Expand All @@ -270,14 +270,14 @@ public CustomTypeSerializer GetSerializerForCustomType(string typeName)
? serializer
: throw new InvalidOperationException($"No serializer found for type '{typeName}'.");
}

/// <summary>
/// The builder of a <see cref="TypeSerializerRegistry"/>.
/// </summary>
public class Builder
{
private readonly List<CustomTypeRegistryEntry> _list = new List<CustomTypeRegistryEntry>();

/// <summary>
/// Creates the <see cref="TypeSerializerRegistry"/>.
/// </summary>
Expand All @@ -293,7 +293,7 @@ public Builder AddCustomType(Type type, CustomTypeSerializer serializer)
if (serializer == null) throw new ArgumentNullException(nameof(serializer));
if (serializer.TypeName == null)
throw new ArgumentException("serializer custom type name can not be null");

_list.Add(new CustomTypeRegistryEntry(type, serializer));
return this;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,11 +134,11 @@ public dynamic ToDict(dynamic objectData)

private IGraphSONSerializer TryGetSerializerFor(Type type)
{
if (Serializers.ContainsKey(type))
if (Serializers.TryGetValue(type, out var serializer))
{
return Serializers[type];
return serializer;
}
foreach (var supportedType in Serializers.Keys)
foreach (var supportedType in new List<Type>(Serializers.Keys))
if (supportedType.IsAssignableFrom(type))
{
return Serializers[supportedType];
Expand Down

0 comments on commit eda4ea6

Please sign in to comment.