mono / mono

Mono open source ECMA CLI, C# and .NET implementation.

Home Page:https://www.mono-project.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Blazor-Wasm: StreamReader.ReadLineAsync fails when called in the while loop header compiled in mode Release and Optimize=true

mkArtakMSFT opened this issue · comments

commented

Issue moved from dotnet/aspnetcore#22595

  • Please respond to @Tewr.

From @Tewr on Friday, June 5, 2020 6:19:32 PM

Describe the bug

The following code fails when compiled with Optimize=true:

public async Task<List<string>> ReadLinesBrokenAsync(Stream stream, Encoding encoding)
 {
     using (var reader = new StreamReader(stream, encoding))
     {
         string line;
         var result = new List<string>();

         while ((line = await reader.ReadLineAsync()) != null)
         {
             result.Add(line);
         }
         return result;
     }
 }

await reader.ReadLineAsync() returns null when it shouldn't.

Workaround:

public async Task<List<string>> ReadLinesWorkingAsync(Stream stream, Encoding encoding)
 {
     using (var reader = new StreamReader(stream, encoding))
     {
         string line;
         var result = new List<string>();
         line = await reader.ReadLineAsync();
         while (line != null)
         {
             result.Add(line);
             line = await reader.ReadLineAsync();
         }
         return result;
     }
 }

... or simply compile without Optimize set to true. Linker settings does not seem to have an impact.

To Reproduce

Minimal repro project: https://github.com/Tewr/BlazorStreamReaderOptimizerBug

Exceptions (if any)

Further technical details

First reported here and later here.

Original reporter also posted here:
https://developercommunity.visualstudio.com/content/problem/1055568/blazor-wasm-release-mode-streamreaderreadlineasync.html

  • ASP.NET Core version
  • Include the output of dotnet --info
    .NET Core SDK (reflecting any global.json):
    Version: 5.0.100-preview.1.20155.7
    Commit: 1c44853056

Runtime Environment:
OS Name: Windows
OS Version: 10.0.18362
OS Platform: Windows
RID: win10-x64
Base Path: C:\Program Files\dotnet\sdk\5.0.100-preview.1.20155.7\

Host (useful for support):
Version: 5.0.0-preview.1.20120.5
Commit: 3c523a6a7a

.NET Core SDKs installed:
2.1.4 [C:\Program Files\dotnet\sdk]
2.1.103 [C:\Program Files\dotnet\sdk]
2.1.200-preview-007474 [C:\Program Files\dotnet\sdk]
2.1.200 [C:\Program Files\dotnet\sdk]
2.1.201 [C:\Program Files\dotnet\sdk]
2.1.202 [C:\Program Files\dotnet\sdk]
2.1.300-preview1-008174 [C:\Program Files\dotnet\sdk]
2.1.300-preview2-008533 [C:\Program Files\dotnet\sdk]
2.1.300 [C:\Program Files\dotnet\sdk]
2.1.400 [C:\Program Files\dotnet\sdk]
2.1.401 [C:\Program Files\dotnet\sdk]
2.1.403 [C:\Program Files\dotnet\sdk]
2.1.503 [C:\Program Files\dotnet\sdk]
2.1.505 [C:\Program Files\dotnet\sdk]
2.1.600-preview-009472 [C:\Program Files\dotnet\sdk]
2.1.601 [C:\Program Files\dotnet\sdk]
2.1.700-preview-009597 [C:\Program Files\dotnet\sdk]
2.1.700-preview-009618 [C:\Program Files\dotnet\sdk]
2.1.800-preview-009696 [C:\Program Files\dotnet\sdk]
2.2.103 [C:\Program Files\dotnet\sdk]
3.0.100-preview8-013656 [C:\Program Files\dotnet\sdk]
3.0.100-preview9-014004 [C:\Program Files\dotnet\sdk]
3.0.100-rc1-014190 [C:\Program Files\dotnet\sdk]
3.0.100 [C:\Program Files\dotnet\sdk]
3.1.101 [C:\Program Files\dotnet\sdk]
3.1.200 [C:\Program Files\dotnet\sdk]
3.1.300-preview-015135 [C:\Program Files\dotnet\sdk]
5.0.100-preview.1.20155.7 [C:\Program Files\dotnet\sdk]

.NET Core runtimes installed:
Microsoft.AspNetCore.All 2.1.0-preview1-final [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.1.0-preview2-final [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.1.0 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.1.2 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.1.3 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.1.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.1.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.1.8 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.1.9 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.1.11 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.1.16 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.2.1 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.App 2.1.0-preview1-final [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.1.0-preview2-final [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.1.0 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.1.2 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.1.3 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.1.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.1.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.1.8 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.1.9 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.1.11 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.1.16 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.2.1 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.0.0-preview7.19365.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.0.0-preview8.19405.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.0.0-preview9.19424.4 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.0.0-rc1.19457.4 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.0.0 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.1.1 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.1.2 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 5.0.0-preview.1.20124.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 2.0.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.0.6 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.0.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.0.9 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.1.0-preview1-26216-03 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.1.0-preview2-26406-04 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.1.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.1.2 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.1.3-servicing-26724-03 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.1.3 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.1.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.1.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.1.8 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.1.9 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.1.11 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.1.16 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.2.1 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.0.0-preview-27324-5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.0.0-preview7-27912-14 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.0.0-preview8-28405-07 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.0.0-preview9-19423-09 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.0.0-rc1-19456-20 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.0.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.1.1 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.1.2 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 5.0.0-preview.1.20120.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 3.0.0-preview7-27912-14 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 3.0.0-preview8-28405-07 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 3.0.0-preview9-19423-09 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 3.0.0-rc1-19456-20 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 3.0.0 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 3.1.1 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 3.1.2 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 5.0.0-preview.1.20127.5 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

  • The IDE (VS / VS Code/ VS4Mac) you're running on, and it's version
    Microsoft Visual Studio Community 2019 Preview
    Version 16.7.0 Preview 1.0

Does this look like potential interpreter bug @BrzVlad ?

I'm not convinced. I can't reproduce this issue by running the code in a standalone wasm sample. Then again, I'm not exactly sure what this Optimize flag does behind the scenes. Locally I had the code compiled using csc 3.5.0 and made sure I passed -optimize+ to it.

commented

I think you might have noticed, and not sure if significant, but my original description of the bug contains a small incorrectnes: await reader.ReadLineAsync() does not return null, it returns the empty string.

Thus, if you pass a string containing newlines as the source, the while loop will loop as many times as you have newlines.

commented

I updated the example repository and removed a lot of code as it turns out this has nothing to do with StreamReader. Just an async call returning string in while header is enough.

The bug should be renamed "Blazor-Wasm: async Task<string> methods fail when called in the while loop header compiled in mode Release and Optimize=true"

Here is the gist of the reproduction of the bug:

public async Task<List<string>> WhileHeaderBrokenAsync()
    {
        string line;
        var result = new List<string>();
        while ((line = await ReadLineAsync()) != null)
        {
            result.Add(line);
        }
        return result;
    }

    public async Task<string> ReadLineAsync()
    {
        this.i++;
        if (this.i > 3)
        {
            return null;
        }

        return i.ToString();
    }

@Tewr That's a nice small repro case. Thanks

Took a look at this. Observed that I can reproduce with release but not with debug and I can't reproduce at all if I include the offending code inside a separate shared library. Checked how the files get compiled with blazor. Turns out that csc compiles with /optimize+ /debug+ even in release mode, but only for blazor app, shared libraries are compiled with /debug-. @mkArtakMSFT Is there a reason for this or is it a bug ? I don't know whether using /debug+ could result in worse code generated by csc.

Using these compile flags I was able to reproduce the failure outside of wasm, with a desktop app and the result is pretty uninteresting. This issue was fixed already with dotnet/runtime#35524

commented

Thanks! @mkArtakMSFT how can I be notified when the fix mentioned above is integrated in blazor, is it already part of a future release?