@@ -12,6 +12,25 @@ open FSharp.NativeInterop
12
12
13
13
#nowarn " 9"
14
14
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
+
15
34
module internal Bytes =
16
35
let b0 n = ( n &&& 0xFF )
17
36
let b1 n = (( n >>> 8 ) &&& 0xFF )
@@ -296,65 +315,72 @@ type ByteMemory with
296
315
member x.AsReadOnly () = ReadOnlyByteMemory x
297
316
298
317
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
301
324
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))
314
332
315
333
static member FromFile ( path , access , ? canShadowCopy : bool ) =
316
334
let canShadowCopy = defaultArg canShadowCopy false
317
335
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
323
347
324
- let mmf , accessor , length =
325
348
let fileStream = File.Open( path, FileMode.Open, access, FileShare.Read)
349
+
326
350
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))
358
384
359
385
static member FromUnsafePointer ( addr , length , holder : obj ) =
360
386
RawByteMemory( NativePtr.ofNativeInt addr, length, holder) :> ByteMemory
0 commit comments