-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Description
Description
Interlocked.Read uses CompareExchange to read a value atomically and with memory ordering guarantees. It takes a readonly ref, which seems to make sense given that it never changes the value.
One could very reasonably use Interlocked.Read to read from a shared memory view with read only access. This causes a crash however because CompareExchange actually does write to the address.
Reproduction Steps
Open a shared memory block with read only access and try to read from it with Interlocked.Read.
I haven't written any C# in a long time so excuse oddities in the example.
using System.IO.MemoryMappedFiles;
Console.WriteLine("Hello, World!");
// Create or open a memory-mapped file
using var memoryMappedFile = MemoryMappedFile.CreateOrOpen("TestFile42", 100, MemoryMappedFileAccess.Read);
// Create a view accessor to access the memory-mapped file
using var accessor = memoryMappedFile.CreateViewAccessor(0, 0, MemoryMappedFileAccess.Read);
// Function to get a reference to the n-th long in the memory-mapped file
unsafe ref long GetNthLong(MemoryMappedViewAccessor accessor, int n)
{
if (n < 0 || n * sizeof(long) >= accessor.Capacity)
{
throw new ArgumentOutOfRangeException(nameof(n), "Index is out of bounds.");
}
byte* pointer = null;
accessor.SafeMemoryMappedViewHandle.AcquirePointer(ref pointer);
try
{
return ref *(long*)(pointer + n * sizeof(long));
}
finally
{
accessor.SafeMemoryMappedViewHandle.ReleasePointer();
}
}
ref readonly long firstLong = ref GetNthLong(accessor, 0); // Get the first long (n = 0)
long readValue = Interlocked.Read(in firstLong); // Atomic read ==> AccessViolationException
//long readValue = firstLong; // Normal read (not atomic)
Console.WriteLine($"first long: {readValue}");
Expected behavior
The function should not advertise itself as non-modifying or should somehow be implemented to actually not require write access.
Actual behavior
The function takes a readonly ref but requires write access to the memory.
Regression?
No response
Known Workarounds
No response
Configuration
I tried this in a .NET 9 console app on Win11 23h2 on x86.
Other information
No response