11// Licensed to the .NET Foundation under one or more agreements.
22// The .NET Foundation licenses this file to you under the MIT license.
33
4+ using System . Diagnostics ;
45using Microsoft . Win32 . SafeHandles ;
56
67namespace System . IO . MemoryMappedFiles
@@ -173,9 +174,6 @@ private static FileStream CreateSharedBackingObject(Interop.Sys.MemoryMappedProt
173174 private static FileStream ? CreateSharedBackingObjectUsingMemory (
174175 Interop . Sys . MemoryMappedProtections protections , long capacity , HandleInheritability inheritability )
175176 {
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-
179177 // Determine the flags to use when creating the shared memory object
180178 Interop . Sys . OpenFlags flags = ( protections & Interop . Sys . MemoryMappedProtections . PROT_WRITE ) != 0 ?
181179 Interop . Sys . OpenFlags . O_RDWR :
@@ -191,22 +189,32 @@ private static FileStream CreateSharedBackingObject(Interop.Sys.MemoryMappedProt
191189 if ( ( protections & Interop . Sys . MemoryMappedProtections . PROT_EXEC ) != 0 )
192190 perms |= Interop . Sys . Permissions . S_IXUSR ;
193191
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
197196 {
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 )
200201 {
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 ( ) ;
207204
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 ) ;
210218
211219 try
212220 {
@@ -236,6 +244,18 @@ private static FileStream CreateSharedBackingObject(Interop.Sys.MemoryMappedProt
236244 fd . Dispose ( ) ;
237245 throw ;
238246 }
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+ }
239259 }
240260
241261 private static FileStream CreateSharedBackingObjectUsingFile ( Interop . Sys . MemoryMappedProtections protections , long capacity , HandleInheritability inheritability )
0 commit comments