Skip to content

Null reference exception related to tuples in union types in Release mode (TaskSeq) #18853

@mrakgr

Description

@mrakgr

Once again, I ran into a bug related to TaskSeq for loops.

Repro steps

Repo: https://github.com/mrakgr/taskseq_bug_report/tree/bug2

module ICF_Main.Main

open System.Threading.Channels
open FSharp.Control

module gRPC =
    type ICF_Proxy_Service_Choices =
        | C_Internal_Reply of string
        | C_Demand_Source_Request of int * string // The error stops happening when I replace the tuple with a singleton type like `string`

    let service () = task {
            let ch_internal_rep = Channel.CreateUnbounded(new UnboundedChannelOptions())
            let ch_demand_source = Channel.CreateUnbounded(new UnboundedChannelOptions())
            let ch_merged = Channel.CreateUnbounded(UnboundedChannelOptions())
            let ch_internal_rep_loop = task { // Replies from the customer cluster
                for x in ch_internal_rep.Reader.ReadAllAsync () do
                    do! ch_merged.Writer.WriteAsync(C_Internal_Reply x)
            }
            let ch_demand_source_loop = task { // Requests from the demand sources for inference requests
                for x in ch_demand_source.Reader.ReadAllAsync () do
                    do! ch_merged.Writer.WriteAsync(C_Demand_Source_Request x)
            }
            let ch_merged_loop = task {
                for x in ch_merged.Reader.ReadAllAsync() do
                    printfn "In ch_merged_loop's loop."
                }
            do! ch_merged_loop
        }

[<EntryPoint>]
let main args =
    let t = gRPC.service()
    t.Wait()
    0

Run it in Release mode with dotnet run -c Release. It only happens in Release mode.

Expected behavior

It waits forever for the task to finish.

Actual behavior

mrakgr@Marko:~/taskseq_bug_report$ dotnet run -c Release
/home/mrakgr/taskseq_bug_report/Program.fs(21,41): warning FS3511: This state machine is not statically compilable. A resumable code invocation at '(22,16--22,19)' could not be reduced. An alternative dynamic implementation will be used, which may be slower. Consider adjusting your code to ensure this state machine is statically compilable, or else suppress this warning.
Unhandled exception. System.NullReferenceException: Object reference not set to an instance of an object.
   at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AwaitUnsafeOnCompleted[TAwaiter](TAwaiter& awaiter, IAsyncStateMachineBox box)
--- End of stack trace from previous location ---
   at System.Threading.Tasks.Task.<>c.<ThrowAsync>b__128_1(Object state)
   at System.Threading.ThreadPoolWorkQueue.Dispatch()
   at System.Threading.PortableThreadPool.WorkerThread.WorkerThreadStart()

Known workarounds

Replace the for loops with TaskSeq.iterAsync calls.

Related information

The setup is same as in: #18848

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    Status

    New

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions