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

Fix JsonRPc Double dispose #6901

Merged
merged 4 commits into from
Apr 8, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,20 @@ public void Can_resize_totally_empty_list()
list.Count.Should().Be(1);
}

[Test]
public void Dispose_recursive()
{
ArrayPoolList<ArrayPoolList<int>> list = new(8)
{
new ArrayPoolList<int>(8),
new ArrayPoolList<int>(8),
new ArrayPoolList<int>(8)
};

list.DisposeRecursive();
list.DisposeRecursive();
}

#if DEBUG
[Test]
[Explicit("Crashes the test runner")]
Expand Down
49 changes: 21 additions & 28 deletions src/Nethermind/Nethermind.Core/Collections/ArrayPoolList.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ public sealed class ArrayPoolList<T> : IList<T>, IList, IOwnedReadOnlyList<T>
{
private readonly ArrayPool<T> _arrayPool;
private T[] _array;
private int _count = 0;
private int _capacity;
private bool _disposed;

Expand All @@ -41,7 +40,7 @@ public ArrayPoolList(ArrayPool<T> arrayPool, int capacity, int startingCount = 0
}
_capacity = _array.Length;

_count = startingCount;
Count = startingCount;
}

ReadOnlySpan<T> IOwnedReadOnlyList<T>.AsSpan()
Expand All @@ -52,7 +51,7 @@ ReadOnlySpan<T> IOwnedReadOnlyList<T>.AsSpan()
public IEnumerator<T> GetEnumerator()
{
GuardDispose();
return new ArrayPoolListEnumerator(_array, _count);
return new ArrayPoolListEnumerator(_array, Count);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
Expand All @@ -75,7 +74,7 @@ static void ThrowObjectDisposed()
public void Add(T item)
{
GuardResize();
_array[_count++] = item;
_array[Count++] = item;
}

int IList.Add(object? value)
Expand All @@ -90,25 +89,25 @@ int IList.Add(object? value)
public void AddRange(ReadOnlySpan<T> items)
{
GuardResize(items.Length);
items.CopyTo(_array.AsSpan(_count, items.Length));
_count += items.Length;
items.CopyTo(_array.AsSpan(Count, items.Length));
Count += items.Length;
}

public void Clear() => _count = 0;
public void Clear() => Count = 0;

public bool Contains(T item)
{
GuardDispose();
int indexOf = Array.IndexOf(_array, item);
return indexOf >= 0 && indexOf < _count;
return indexOf >= 0 && indexOf < Count;
}

bool IList.Contains(object? value) => IsCompatibleObject(value) && Contains((T)value!);

public void CopyTo(T[] array, int arrayIndex)
{
GuardDispose();
_array.AsMemory(0, _count).CopyTo(array.AsMemory(arrayIndex));
_array.AsMemory(0, Count).CopyTo(array.AsMemory(arrayIndex));
}

void ICollection.CopyTo(Array array, int index)
Expand All @@ -118,17 +117,10 @@ void ICollection.CopyTo(Array array, int index)

GuardDispose();

Array.Copy(_array, 0, array!, index, _count);
Array.Copy(_array, 0, array!, index, Count);
}

public int Count
{
get
{
GuardDispose();
return _count;
}
}
public int Count { get; private set; } = 0;

public int Capacity => _capacity;

Expand All @@ -146,7 +138,7 @@ public int IndexOf(T item)
{
GuardDispose();
int indexOf = Array.IndexOf(_array, item);
return indexOf < _count ? indexOf : -1;
return indexOf < Count ? indexOf : -1;
}

int IList.IndexOf(object? value) => IsCompatibleObject(value) ? IndexOf((T)value!) : -1;
Expand All @@ -155,9 +147,9 @@ public void Insert(int index, T item)
{
GuardResize();
GuardIndex(index, allowEqualToCount: true);
_array.AsMemory(index, _count - index).CopyTo(_array.AsMemory(index + 1));
_array.AsMemory(index, Count - index).CopyTo(_array.AsMemory(index + 1));
_array[index] = item;
_count++;
Count++;
}

void IList.Insert(int index, object? value)
Expand All @@ -170,7 +162,7 @@ void IList.Insert(int index, object? value)
private void GuardResize(int itemsToAdd = 1)
{
GuardDispose();
int newCount = _count + itemsToAdd;
int newCount = Count + itemsToAdd;
if (_capacity == 0)
{
_array = _arrayPool.Rent(newCount);
Expand Down Expand Up @@ -208,12 +200,12 @@ private bool RemoveAtInternal(int index, bool shouldThrow)
if (isValid)
{
int start = index + 1;
if (start < _count)
if (start < Count)
{
_array.AsMemory(start, _count - index).CopyTo(_array.AsMemory(index));
_array.AsMemory(start, Count - index).CopyTo(_array.AsMemory(index));
}

_count--;
Count--;
}

return isValid;
Expand All @@ -223,7 +215,7 @@ public void Truncate(int newLength)
{
GuardDispose();
GuardIndex(newLength, allowEqualToCount: true);
_count = newLength;
Count = newLength;
}

public T this[int index]
Expand Down Expand Up @@ -254,7 +246,7 @@ public T this[int index]
private bool GuardIndex(int index, bool shouldThrow = true, bool allowEqualToCount = false)
{
GuardDispose();
int count = _count;
int count = Count;
if ((uint)index > (uint)count || (!allowEqualToCount && index == count))
{
if (shouldThrow)
Expand Down Expand Up @@ -300,6 +292,7 @@ public void Dispose()
if (!_disposed)
{
_disposed = true;
Count = 0;
T[]? array = _array;
if (array is not null)
{
Expand All @@ -325,5 +318,5 @@ public void Dispose()
}
#endif

public Span<T> AsSpan() => _array.AsSpan(0, _count);
public Span<T> AsSpan() => _array.AsSpan(0, Count);
}
5 changes: 1 addition & 4 deletions src/Nethermind/Nethermind.Runner/JsonRpc/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -213,10 +213,7 @@ await PushErrorResponse(StatusCodes.Status403Forbidden, ErrorCodes.InvalidReques
}
else
{
using (result.Response)
{
jsonSerializer.Serialize(resultWriter, result.Response);
}
jsonSerializer.Serialize(resultWriter, result.Response);
}

if (stream is not null)
Expand Down
Loading