1
1
// Licensed to the .NET Foundation under one or more agreements.
2
2
// The .NET Foundation licenses this file to you under the MIT license.
3
3
4
+ using System . Diagnostics ;
4
5
using Microsoft . Win32 . SafeHandles ;
5
6
6
7
namespace System . IO . MemoryMappedFiles
@@ -173,9 +174,6 @@ private static FileStream CreateSharedBackingObject(Interop.Sys.MemoryMappedProt
173
174
private static FileStream ? CreateSharedBackingObjectUsingMemory (
174
175
Interop . Sys . MemoryMappedProtections protections , long capacity , HandleInheritability inheritability )
175
176
{
176
- // The POSIX shared memory object name must begin with '/'. After that we just want something short and unique.
177
- string mapName = string . Create ( null , stackalloc char [ 128 ] , $ "/corefx_map_{ Guid . NewGuid ( ) : N} ") ;
178
-
179
177
// Determine the flags to use when creating the shared memory object
180
178
Interop . Sys . OpenFlags flags = ( protections & Interop . Sys . MemoryMappedProtections . PROT_WRITE ) != 0 ?
181
179
Interop . Sys . OpenFlags . O_RDWR :
@@ -191,22 +189,32 @@ private static FileStream CreateSharedBackingObject(Interop.Sys.MemoryMappedProt
191
189
if ( ( protections & Interop . Sys . MemoryMappedProtections . PROT_EXEC ) != 0 )
192
190
perms |= Interop . Sys . Permissions . S_IXUSR ;
193
191
194
- // Create the shared memory object.
195
- SafeFileHandle fd = Interop . Sys . ShmOpen ( mapName , flags , ( int ) perms ) ;
196
- if ( fd . IsInvalid )
192
+ string mapName ;
193
+ SafeFileHandle fd ;
194
+
195
+ do
197
196
{
198
- Interop . ErrorInfo errorInfo = Interop . Sys . GetLastErrorInfo ( ) ;
199
- if ( errorInfo . Error == Interop . Error . ENOTSUP )
197
+ mapName = GenerateMapName ( ) ;
198
+ fd = Interop . Sys . ShmOpen ( mapName , flags , ( int ) perms ) ; // Create the shared memory object.
199
+
200
+ if ( fd . IsInvalid )
200
201
{
201
- // If ShmOpen is not supported, fall back to file backing object.
202
- // Note that the System.Native shim will force this failure on platforms where
203
- // the result of native shm_open does not work well with our subsequent call
204
- // to mmap.
205
- return null ;
206
- }
202
+ Interop . ErrorInfo errorInfo = Interop . Sys . GetLastErrorInfo ( ) ;
203
+ fd . Dispose ( ) ;
207
204
208
- throw Interop . GetExceptionForIoErrno ( errorInfo ) ;
209
- }
205
+ if ( errorInfo . Error == Interop . Error . ENOTSUP )
206
+ {
207
+ // If ShmOpen is not supported, fall back to file backing object.
208
+ // Note that the System.Native shim will force this failure on platforms where
209
+ // the result of native shm_open does not work well with our subsequent call to mmap.
210
+ return null ;
211
+ }
212
+ else if ( errorInfo . Error != Interop . Error . EEXIST ) // map with same name already existed
213
+ {
214
+ throw Interop . GetExceptionForIoErrno ( errorInfo ) ;
215
+ }
216
+ }
217
+ } while ( fd . IsInvalid ) ;
210
218
211
219
try
212
220
{
@@ -236,6 +244,18 @@ private static FileStream CreateSharedBackingObject(Interop.Sys.MemoryMappedProt
236
244
fd . Dispose ( ) ;
237
245
throw ;
238
246
}
247
+
248
+ static string GenerateMapName ( )
249
+ {
250
+ const int MaxSharedMemoryObjectNameLength = 32 ; // SHM_NAME_MAX on OSX ARM64, on other systems it's equal PATH_MAX (250)
251
+ // The POSIX shared memory object name must begin with '/'. After that we just want something short (32) and unique.
252
+ return string . Create ( MaxSharedMemoryObjectNameLength , 0 , ( span , state ) =>
253
+ {
254
+ Guid . NewGuid ( ) . TryFormat ( span , out int charsWritten , "N" ) ;
255
+ Debug . Assert ( charsWritten == MaxSharedMemoryObjectNameLength ) ;
256
+ "/dotnet_" . CopyTo ( span ) ;
257
+ } ) ;
258
+ }
239
259
}
240
260
241
261
private static FileStream CreateSharedBackingObjectUsingFile ( Interop . Sys . MemoryMappedProtections protections , long capacity , HandleInheritability inheritability )
0 commit comments