Skip to content

Commit 2b85b55

Browse files
Merge pull request #1756 from SixLabors/af/fix-1755
Fix ManagedBufferBase pinning behavior
2 parents ffa3935 + 289e9f8 commit 2b85b55

File tree

3 files changed

+40
-3
lines changed

3 files changed

+40
-3
lines changed

src/ImageSharp/Memory/Allocators/Internals/ManagedBufferBase.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ public override unsafe MemoryHandle Pin(int elementIndex = 0)
2424
}
2525

2626
void* ptr = (void*)this.pinHandle.AddrOfPinnedObject();
27-
return new MemoryHandle(ptr, this.pinHandle);
27+
28+
// We should only pass pinnable:this, when GCHandle lifetime is managed by the MemoryManager<T> instance.
29+
return new MemoryHandle(ptr, pinnable: this);
2830
}
2931

3032
/// <inheritdoc />
@@ -42,4 +44,4 @@ public override void Unpin()
4244
/// <returns>The pinnable <see cref="object"/>.</returns>
4345
protected abstract object GetPinnableObject();
4446
}
45-
}
47+
}

tests/ImageSharp.Tests/Memory/Allocators/ArrayPoolMemoryAllocatorTests.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,23 @@ public void CleaningRequests_AreControlledByAllocationParameter_Clean(Allocation
114114
}
115115
}
116116

117+
[Fact]
118+
public unsafe void Allocate_MemoryIsPinnableMultipleTimes()
119+
{
120+
ArrayPoolMemoryAllocator allocator = this.LocalFixture.MemoryAllocator;
121+
using IMemoryOwner<byte> memoryOwner = allocator.Allocate<byte>(100);
122+
123+
using (MemoryHandle pin = memoryOwner.Memory.Pin())
124+
{
125+
Assert.NotEqual(IntPtr.Zero, (IntPtr)pin.Pointer);
126+
}
127+
128+
using (MemoryHandle pin = memoryOwner.Memory.Pin())
129+
{
130+
Assert.NotEqual(IntPtr.Zero, (IntPtr)pin.Pointer);
131+
}
132+
}
133+
117134
[Theory]
118135
[InlineData(false)]
119136
[InlineData(true)]

tests/ImageSharp.Tests/Memory/Allocators/SimpleGcMemoryAllocatorTests.cs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the Apache License, Version 2.0.
33

44
using System;
5+
using System.Buffers;
56
using System.Runtime.InteropServices;
67
using SixLabors.ImageSharp.Memory;
78
using Xunit;
@@ -36,9 +37,26 @@ public void AllocateManagedByteBuffer_IncorrectAmount_ThrowsCorrect_ArgumentOutO
3637
Assert.Equal("length", ex.ParamName);
3738
}
3839

40+
[Fact]
41+
public unsafe void Allocate_MemoryIsPinnableMultipleTimes()
42+
{
43+
SimpleGcMemoryAllocator allocator = this.MemoryAllocator;
44+
using IMemoryOwner<byte> memoryOwner = allocator.Allocate<byte>(100);
45+
46+
using (MemoryHandle pin = memoryOwner.Memory.Pin())
47+
{
48+
Assert.NotEqual(IntPtr.Zero, (IntPtr)pin.Pointer);
49+
}
50+
51+
using (MemoryHandle pin = memoryOwner.Memory.Pin())
52+
{
53+
Assert.NotEqual(IntPtr.Zero, (IntPtr)pin.Pointer);
54+
}
55+
}
56+
3957
[StructLayout(LayoutKind.Explicit, Size = 512)]
4058
private struct BigStruct
4159
{
4260
}
4361
}
44-
}
62+
}

0 commit comments

Comments
 (0)