Skip to content

fixed/pinned array escapes due to tail call #18689

Open
@luithefirst

Description

@luithefirst

We have identified a scenario where an assumed pinned array is moved before being copied, resulting in an AccessVioloationException. It can be reproduced with net48, net8.0, and netstandard 2.0 when compiled with Tailcalls true (only tested on Windows), SDK version 9.0.203.

In particular, it escapes from an extension method like this:

static member Set<'T when 'T : unmanaged>(this : IBuffer, src : 'T[]) =
    use ptr = fixed src
    this.Set(ptr |> NativePtr.toNativeInt, nativeint src.Length * nativeint sizeof<'T>)

You can find a repository with a minimal example here:
https://github.com/luithefirst/TailCallEscape

It will crash in about 1 min. Originally, I could also see a TailCallHelperStub stack frame in WinDbg, but it is gone now in my minimal example. Still, if Tailcalls is set to false in the fsproj file, the issue cannot be reproduced.

A colleague also recalled a possible similar issue back in net 5, but I could not find any details on it.

This is where the issue actually occurs in our framework:
https://github.com/aardvark-platform/aardvark.rendering/blob/646d165829283a3a0ba03cb4badc465245fbc670/src/Aardvark.Rendering/Resources/Adaptive/ManagedBuffer.fs#L105
https://github.com/aardvark-platform/aardvark.base/blob/5b0b5c0507ca20238899260d2a08d252e6a4f1e8/src/Aardvark.Base.FSharp/Utilities/Interop/FSLibExtensions.fs#L529

There, it is implemented in a netstandard 2.0 library, and when consumed by net48 the issue occurs (but for some reason not in net8.0). Also, when disabling Tailcalls in the library, it can be avoided.

Expected behaviour: The compiler should be aware that a stackframe is pinning an object and therefore should not generate a tailcall.

Workaround: Use GCHandle + AddrOfPinnedObject

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    Status

    New

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions