@@ -12,6 +12,25 @@ open FSharp.NativeInterop
1212
1313#nowarn " 9"
1414
15+ module Utils =
16+ let runningOnMono =
17+ #if ENABLE_ MONO_ SUPPORT
18+ // Officially supported way to detect if we are running on Mono.
19+ // See http://www.mono-project.com/FAQ:_Technical
20+ // "How can I detect if am running in Mono?" section
21+ try
22+ System.Type.GetType ( " Mono.Runtime" ) <> null
23+ with _ ->
24+ // Must be robust in the case that someone else has installed a handler into System.AppDomain.OnTypeResolveEvent
25+ // that is not reliable.
26+ // This is related to bug 5506--the issue is actually a bug in VSTypeResolutionService.EnsurePopulated which is
27+ // called by OnTypeResolveEvent. The function throws a NullReferenceException. I'm working with that team to get
28+ // their issue fixed but we need to be robust here anyway.
29+ false
30+ #else
31+ false
32+ #endif
33+
1534module internal Bytes =
1635 let b0 n = ( n &&& 0xFF )
1736 let b1 n = (( n >>> 8 ) &&& 0xFF )
@@ -296,65 +315,72 @@ type ByteMemory with
296315 member x.AsReadOnly () = ReadOnlyByteMemory x
297316
298317 static member CreateMemoryMappedFile ( bytes : ReadOnlyByteMemory ) =
299- let length = int64 bytes.Length
300- let mmf =
318+ if Utils.runningOnMono
319+ then
320+ // mono's MemoryMappedFile implementation throws with null `mapName`, so we use byte arrays instead: https://github.com/mono/mono/issues/10245
321+ ByteArrayMemory.FromArray ( bytes.ToArray()) :> ByteMemory
322+ else
323+ let length = int64 bytes.Length
301324 let mmf =
302- MemoryMappedFile.CreateNew(
303- null ,
304- length,
305- MemoryMappedFileAccess.ReadWrite,
306- MemoryMappedFileOptions.None,
307- HandleInheritability.None)
308- use stream = mmf.CreateViewStream( 0 L, length, MemoryMappedFileAccess.ReadWrite)
309- bytes.CopyTo stream
310- mmf
311-
312- let accessor = mmf.CreateViewAccessor( 0 L, length, MemoryMappedFileAccess.ReadWrite)
313- RawByteMemory.FromUnsafePointer( accessor.SafeMemoryMappedViewHandle.DangerousGetHandle(), int length, ( mmf, accessor))
325+ let mmf = MemoryMappedFile.CreateNew( null , length, MemoryMappedFileAccess.ReadWrite, MemoryMappedFileOptions.None, HandleInheritability.None)
326+ use stream = mmf.CreateViewStream( 0 L, length, MemoryMappedFileAccess.ReadWrite)
327+ bytes.CopyTo stream
328+ mmf
329+
330+ let accessor = mmf.CreateViewAccessor( 0 L, length, MemoryMappedFileAccess.ReadWrite)
331+ RawByteMemory.FromUnsafePointer( accessor.SafeMemoryMappedViewHandle.DangerousGetHandle(), int length, ( mmf, accessor))
314332
315333 static member FromFile ( path , access , ? canShadowCopy : bool ) =
316334 let canShadowCopy = defaultArg canShadowCopy false
317335
318- let memoryMappedFileAccess =
319- match access with
320- | FileAccess.Read -> MemoryMappedFileAccess.Read
321- | FileAccess.Write -> MemoryMappedFileAccess.Write
322- | _ -> MemoryMappedFileAccess.ReadWrite
336+ if Utils.runningOnMono
337+ then
338+ // mono's MemoryMappedFile implementation throws with null `mapName`, so we use byte arrays instead: https://github.com/mono/mono/issues/10245
339+ let bytes = File.ReadAllBytes path
340+ ByteArrayMemory.FromArray bytes
341+ else
342+ let memoryMappedFileAccess =
343+ match access with
344+ | FileAccess.Read -> MemoryMappedFileAccess.Read
345+ | FileAccess.Write -> MemoryMappedFileAccess.Write
346+ | _ -> MemoryMappedFileAccess.ReadWrite
323347
324- let mmf , accessor , length =
325348 let fileStream = File.Open( path, FileMode.Open, access, FileShare.Read)
349+
326350 let length = fileStream.Length
327- let mmf =
328- if canShadowCopy then
329- let mmf =
330- MemoryMappedFile.CreateNew(
331- null ,
332- length,
333- MemoryMappedFileAccess.ReadWrite,
334- MemoryMappedFileOptions.None,
335- HandleInheritability.None)
336- use stream = mmf.CreateViewStream( 0 L, length, MemoryMappedFileAccess.ReadWrite)
337- fileStream.CopyTo( stream)
338- fileStream.Dispose()
339- mmf
340- else
341- MemoryMappedFile.CreateFromFile(
342- fileStream,
343- null ,
344- length,
345- memoryMappedFileAccess,
346- HandleInheritability.None,
347- leaveOpen= false )
348- mmf, mmf.CreateViewAccessor( 0 L, length, memoryMappedFileAccess), length
349-
350- // Validate MMF with the access that was intended.
351- match access with
352- | FileAccess.Read when not accessor.CanRead -> invalidOp " Cannot read file"
353- | FileAccess.Write when not accessor.CanWrite -> invalidOp " Cannot write file"
354- | FileAccess.ReadWrite when not accessor.CanRead || not accessor.CanWrite -> invalidOp " Cannot read or write file"
355- | _ -> ()
356-
357- RawByteMemory.FromUnsafePointer( accessor.SafeMemoryMappedViewHandle.DangerousGetHandle(), int length, ( mmf, accessor))
351+
352+ let mmf , accessor , length =
353+ let mmf =
354+ if canShadowCopy then
355+ let mmf =
356+ MemoryMappedFile.CreateNew(
357+ null ,
358+ length,
359+ MemoryMappedFileAccess.ReadWrite,
360+ MemoryMappedFileOptions.None,
361+ HandleInheritability.None)
362+ use stream = mmf.CreateViewStream( 0 L, length, MemoryMappedFileAccess.ReadWrite)
363+ fileStream.CopyTo( stream)
364+ fileStream.Dispose()
365+ mmf
366+ else
367+ MemoryMappedFile.CreateFromFile(
368+ fileStream,
369+ null ,
370+ length,
371+ memoryMappedFileAccess,
372+ HandleInheritability.None,
373+ leaveOpen= false )
374+ mmf, mmf.CreateViewAccessor( 0 L, length, memoryMappedFileAccess), length
375+
376+ // Validate MMF with the access that was intended.
377+ match access with
378+ | FileAccess.Read when not accessor.CanRead -> invalidOp " Cannot read file"
379+ | FileAccess.Write when not accessor.CanWrite -> invalidOp " Cannot write file"
380+ | FileAccess.ReadWrite when not accessor.CanRead || not accessor.CanWrite -> invalidOp " Cannot read or write file"
381+ | _ -> ()
382+
383+ RawByteMemory.FromUnsafePointer( accessor.SafeMemoryMappedViewHandle.DangerousGetHandle(), int length, ( mmf, accessor))
358384
359385 static member FromUnsafePointer ( addr , length , holder : obj ) =
360386 RawByteMemory( NativePtr.ofNativeInt addr, length, holder) :> ByteMemory
0 commit comments