diff --git a/src/System.IO.MemoryMappedFiles/src/Interop/Interop.Windows.cs b/src/System.IO.MemoryMappedFiles/src/Interop/Interop.Windows.cs
index 3a67d18cfaa2..5d6017cdb127 100644
--- a/src/System.IO.MemoryMappedFiles/src/Interop/Interop.Windows.cs
+++ b/src/System.IO.MemoryMappedFiles/src/Interop/Interop.Windows.cs
@@ -129,6 +129,7 @@ internal static partial class Interop
// From WinBase.h
internal const int SEM_FAILCRITICALERRORS = 1;
+ internal static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
[StructLayout(LayoutKind.Sequential)]
internal struct SYSTEM_INFO
@@ -209,6 +210,12 @@ internal static extern SafeMemoryMappedFileHandle CreateFileMapping(SafeFileHand
ref SECURITY_ATTRIBUTES lpFileMappingAttributes, int flProtect,
int dwMaximumSizeHigh, int dwMaximumSizeLow, string lpName);
+ [DllImport(MEMORYDLL, EntryPoint = "CreateFileMappingW", CharSet = CharSet.Unicode, SetLastError = true)]
+ [SecurityCritical]
+ internal static extern SafeMemoryMappedFileHandle CreateFileMapping(IntPtr hFile,
+ ref SECURITY_ATTRIBUTES lpFileMappingAttributes, int flProtect,
+ int dwMaximumSizeHigh, int dwMaximumSizeLow, string lpName);
+
[DllImport(MEMORYDLL, EntryPoint = "OpenFileMappingW", CharSet = CharSet.Unicode, SetLastError = true)]
[SecurityCritical]
internal static extern SafeMemoryMappedFileHandle OpenFileMapping(
diff --git a/src/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedFile.Unix.cs b/src/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedFile.Unix.cs
index 77550eb5525d..4382eef199cd 100644
--- a/src/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedFile.Unix.cs
+++ b/src/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedFile.Unix.cs
@@ -9,7 +9,7 @@ namespace System.IO.MemoryMappedFiles
public partial class MemoryMappedFile
{
///
- /// Used by the 2 Create factory method groups. A -1 fileHandle specifies that the
+ /// Used by the 2 Create factory method groups. A null fileHandle specifies that the
/// memory mapped file should not be associated with an exsiting file on disk (ie start
/// out empty).
///
@@ -46,19 +46,7 @@ private static SafeMemoryMappedFileHandle OpenCore(
}
///
- /// Used by the CreateOrOpen factory method groups. A -1 fileHandle specifies that the
- /// memory mapped file should not be associated with an existing file on disk (ie start
- /// out empty).
- ///
- /// Try to open the file if it exists -- this requires a bit more work. Loop until we can
- /// either create or open a memory mapped file up to a timeout. CreateFileMapping may fail
- /// if the file exists and we have non-null security attributes, in which case we need to
- /// use OpenFileMapping. But, there exists a race condition because the memory mapped file
- /// may have closed inbetween the two calls -- hence the loop.
- ///
- /// This uses similar retry/timeout logic as in performance counter. It increases the wait
- /// time each pass through the loop and times out in approximately 1.4 minutes. If after
- /// retrying, a MMF handle still hasn't been opened, throw an InvalidOperationException.
+ /// Used by the CreateOrOpen factory method groups.
///
[SecurityCritical]
private static SafeMemoryMappedFileHandle CreateOrOpenCore(
diff --git a/src/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedFile.Windows.cs b/src/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedFile.Windows.cs
index fd64a2a87b32..4f968ecca975 100644
--- a/src/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedFile.Windows.cs
+++ b/src/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedFile.Windows.cs
@@ -5,14 +5,14 @@
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Security;
-using System.Threading.Tasks;
+using System.Threading;
namespace System.IO.MemoryMappedFiles
{
public partial class MemoryMappedFile
{
///
- /// Used by the 2 Create factory method groups. A -1 fileHandle specifies that the
+ /// Used by the 2 Create factory method groups. A null fileHandle specifies that the
/// memory mapped file should not be associated with an exsiting file on disk (ie start
/// out empty).
///
@@ -21,21 +21,24 @@ private static SafeMemoryMappedFileHandle CreateCore(
SafeFileHandle fileHandle, String mapName, HandleInheritability inheritability,
MemoryMappedFileAccess access, MemoryMappedFileOptions options, Int64 capacity)
{
- SafeMemoryMappedFileHandle handle = null;
Interop.SECURITY_ATTRIBUTES secAttrs = GetSecAttrs(inheritability);
// split the long into two ints
int capacityLow = unchecked((int)(capacity & 0x00000000FFFFFFFFL));
int capacityHigh = unchecked((int)(capacity >> 32));
- handle = Interop.mincore.CreateFileMapping(fileHandle, ref secAttrs, GetPageAccess(access) | (int)options,
- capacityHigh, capacityLow, mapName);
+ SafeMemoryMappedFileHandle handle = fileHandle != null ?
+ Interop.mincore.CreateFileMapping(fileHandle, ref secAttrs, GetPageAccess(access) | (int)options, capacityHigh, capacityLow, mapName) :
+ Interop.mincore.CreateFileMapping(Interop.INVALID_HANDLE_VALUE, ref secAttrs, GetPageAccess(access) | (int)options, capacityHigh, capacityLow, mapName);
Int32 errorCode = Marshal.GetLastWin32Error();
- if (!handle.IsInvalid && errorCode == Interop.ERROR_ALREADY_EXISTS)
+ if (!handle.IsInvalid)
{
- handle.Dispose();
- throw Win32Marshal.GetExceptionForWin32Error(errorCode);
+ if (errorCode == Interop.ERROR_ALREADY_EXISTS)
+ {
+ handle.Dispose();
+ throw Win32Marshal.GetExceptionForWin32Error(errorCode);
+ }
}
else if (handle.IsInvalid)
{
@@ -68,26 +71,23 @@ private static SafeMemoryMappedFileHandle OpenCore(
}
///
- /// Used by the CreateOrOpen factory method groups. A -1 fileHandle specifies that the
- /// memory mapped file should not be associated with an existing file on disk (ie start
- /// out empty).
- ///
- /// Try to open the file if it exists -- this requires a bit more work. Loop until we can
- /// either create or open a memory mapped file up to a timeout. CreateFileMapping may fail
- /// if the file exists and we have non-null security attributes, in which case we need to
- /// use OpenFileMapping. But, there exists a race condition because the memory mapped file
- /// may have closed inbetween the two calls -- hence the loop.
- ///
- /// This uses similar retry/timeout logic as in performance counter. It increases the wait
- /// time each pass through the loop and times out in approximately 1.4 minutes. If after
- /// retrying, a MMF handle still hasn't been opened, throw an InvalidOperationException.
+ /// Used by the CreateOrOpen factory method groups.
///
[SecurityCritical]
- private static SafeMemoryMappedFileHandle CreateOrOpenCore(SafeFileHandle fileHandle, String mapName,
- HandleInheritability inheritability,
- MemoryMappedFileAccess access, MemoryMappedFileOptions options,
- Int64 capacity)
+ private static SafeMemoryMappedFileHandle CreateOrOpenCore(
+ String mapName, HandleInheritability inheritability, MemoryMappedFileAccess access,
+ MemoryMappedFileOptions options, Int64 capacity)
{
+ /// Try to open the file if it exists -- this requires a bit more work. Loop until we can
+ /// either create or open a memory mapped file up to a timeout. CreateFileMapping may fail
+ /// if the file exists and we have non-null security attributes, in which case we need to
+ /// use OpenFileMapping. But, there exists a race condition because the memory mapped file
+ /// may have closed inbetween the two calls -- hence the loop.
+ ///
+ /// The retry/timeout logic increases the wait time each pass through the loop and times
+ /// out in approximately 1.4 minutes. If after retrying, a MMF handle still hasn't been opened,
+ /// throw an InvalidOperationException.
+
Debug.Assert(access != MemoryMappedFileAccess.Write, "Callers requesting write access shouldn't try to create a mmf");
SafeMemoryMappedFileHandle handle = null;
@@ -104,31 +104,25 @@ private static SafeMemoryMappedFileHandle CreateOrOpenCore(SafeFileHandle fileHa
while (waitRetries > 0)
{
// try to create
- handle = Interop.mincore.CreateFileMapping(fileHandle, ref secAttrs,
+ handle = Interop.mincore.CreateFileMapping(Interop.INVALID_HANDLE_VALUE, ref secAttrs,
GetPageAccess(access) | (int)options, capacityHigh, capacityLow, mapName);
- Int32 createErrorCode = Marshal.GetLastWin32Error();
if (!handle.IsInvalid)
{
break;
}
else
{
+ Int32 createErrorCode = Marshal.GetLastWin32Error();
if (createErrorCode != Interop.ERROR_ACCESS_DENIED)
{
throw Win32Marshal.GetExceptionForWin32Error(createErrorCode);
}
-
- // the mapname exists but our ACL is preventing us from opening it with CreateFileMapping.
- // Let's try to open it with OpenFileMapping.
- handle.SetHandleAsInvalid();
}
// try to open
handle = Interop.mincore.OpenFileMapping(GetFileMapAccess(access), (inheritability &
- HandleInheritability.Inheritable) != 0, mapName);
-
- Int32 openErrorCode = Marshal.GetLastWin32Error();
+ HandleInheritability.Inheritable) != 0, mapName);
// valid handle
if (!handle.IsInvalid)
@@ -138,6 +132,7 @@ private static SafeMemoryMappedFileHandle CreateOrOpenCore(SafeFileHandle fileHa
// didn't get valid handle; have to retry
else
{
+ Int32 openErrorCode = Marshal.GetLastWin32Error();
if (openErrorCode != Interop.ERROR_FILE_NOT_FOUND)
{
throw Win32Marshal.GetExceptionForWin32Error(openErrorCode);
@@ -151,7 +146,7 @@ private static SafeMemoryMappedFileHandle CreateOrOpenCore(SafeFileHandle fileHa
}
else
{
- Task.Delay(waitSleep).Wait();
+ ThreadSleep(waitSleep);
waitSleep *= 2;
}
}
@@ -258,5 +253,13 @@ private unsafe static Interop.SECURITY_ATTRIBUTES GetSecAttrs(HandleInheritabili
}
return secAttrs;
}
+
+ ///
+ /// Replacement for Thread.Sleep(milliseconds), which isn't available.
+ ///
+ internal static void ThreadSleep(int milliseconds)
+ {
+ new ManualResetEventSlim(initialState: false).Wait(milliseconds);
+ }
}
}
diff --git a/src/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedFile.cs b/src/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedFile.cs
index 7f234a23404b..c0424f7d1e1b 100644
--- a/src/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedFile.cs
+++ b/src/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedFile.cs
@@ -305,9 +305,7 @@ public static MemoryMappedFile CreateNew(String mapName, Int64 capacity, MemoryM
throw new ArgumentOutOfRangeException("inheritability");
}
- SafeMemoryMappedFileHandle handle = CreateCore(new SafeFileHandle(new IntPtr(-1), true), mapName, inheritability,
- access, options, capacity);
-
+ SafeMemoryMappedFileHandle handle = CreateCore(null, mapName, inheritability, access, options, capacity);
return new MemoryMappedFile(handle);
}
@@ -376,7 +374,7 @@ public static MemoryMappedFile CreateOrOpen(String mapName, Int64 capacity,
}
else
{
- handle = CreateOrOpenCore(new SafeFileHandle(new IntPtr(-1), true), mapName, inheritability, access, options, capacity);
+ handle = CreateOrOpenCore(mapName, inheritability, access, options, capacity);
}
return new MemoryMappedFile(handle);
}
diff --git a/src/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedView.Windows.cs b/src/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedView.Windows.cs
index 9badc11bb131..cedfadb2c273 100644
--- a/src/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedView.Windows.cs
+++ b/src/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedView.Windows.cs
@@ -140,7 +140,7 @@ public void Flush(UIntPtr capacity)
for (Int32 w = 0; canRetry && w < MaxFlushWaits; w++)
{
Int32 pause = (1 << w); // MaxFlushRetries should never be over 30
- Task.Delay(pause).Wait();
+ MemoryMappedFile.ThreadSleep(pause);
for (Int32 r = 0; canRetry && r < MaxFlushRetriesPerWait; r++)
{