Skip to content

[RuntimeAsync] NullReferenceException crash in some scenarios in System.Text.Json.Serialization.Tests.PipeTests #121564

@VSadov

Description

@VSadov

The failure only happens on Linux and the number of failures is not stable - sometimes I see 2 sometimes 4. Locally I typically see 4.

I suspect we have some kind of GC hole.

Example of a failure in the CI:
https://helixr1107v0xdcypoyl9e7f.blob.core.windows.net/dotnet-runtime-refs-pull-119432-merge-985956b1db93433192/System.Text.Json.Tests/1/console.fe1637fd.log?helixlogtype=result

The problem code looks like:

        internal async ValueTask<T?> DeserializeAsync<TReadBufferState, TStream>(TStream utf8Json, TReadBufferState bufferState, CancellationToken cancellationToken)
            where TReadBufferState : struct, IReadBufferState<TReadBufferState, TStream>
        {
            Debug.Assert(IsConfigured);
            JsonSerializerOptions options = Options;
            ReadStack readStack = default;
            readStack.Initialize(this, supportContinuation: true);
            var jsonReaderState = new JsonReaderState(options.GetReaderOptions());

            try
            {
                while (true)
                {
                    bufferState = await bufferState.ReadAsync(utf8Json, cancellationToken).ConfigureAwait(false);

                    bool success = ContinueDeserialize<TReadBufferState, TStream>(
                        ref bufferState,
                        ref jsonReaderState,
                        ref readStack,
                        out T? value);

                    if (success)
                    {
                        return value;
                    }
                }
            }
            finally
            {
                bufferState.Dispose();
            }
        }

Right before the await the bufferState._utf8Json is not null. Once cancelation exception is thrown, we get to finally, which calls bufferState.Dispose().

Inside bufferState.Dispose() the bufferState._utf8Json is somehow null and _utf8Json.AdvanceTo(_sequence.Start); throws NRE.

The result is failures like:

    System.Text.Json.Serialization.Tests.PipeTests+PipeTests_AsyncWithSmallBuffer.CancelPendingReadThrows [FAIL]
      Assert.Throws() Failure: Exception type was not an exact match
      Expected: typeof(System.OperationCanceledException)
      Actual:   typeof(System.NullReferenceException)
      ---- System.NullReferenceException : Object reference not set to an instance of an object.
      Stack Trace:
        /_/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/Pipe.ReadTests.cs(97,0): at System.Text.Json.Serialization.Tests.PipeTests.CancelPendingReadThrows()
        --- End of stack trace from previous location ---
        --- End of stack trace from previous location ---
        ----- Inner Stack Trace -----
        /_/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/PipeReadBufferState.cs(149,0): at System.Text.Json.Serialization.PipeReadBufferState.Dispose()
        /_/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfoOfT.ReadHelper.cs(54,0): at System.Text.Json.Serialization.Metadata.JsonTypeInfo`1.DeserializeAsync[TReadBufferState,TStream](TStream utf8Json, TReadBufferState bufferState, CancellationToken cancellationToken)
        /_/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.CoreCLR.cs(467,0): at System.Runtime.CompilerServices.AsyncHelpers.RuntimeAsyncTaskCore.DispatchContinuations[T,TOps](T task)
        --- End of stack trace from previous location ---
        /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.cs(99,0): at System.Runtime.CompilerServices.AsyncHelpers.Await(Task task)
           at System.Text.Json.Serialization.Tests.PipeTests.<>c__DisplayClass4_0.<CancelPendingReadThrows>b__0()
        --- End of stack trace from previous location ---

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMIos-linuxLinux OS (any supported distro)runtime-async

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions