Skip to content

.NET 4.7 JIT creates infinite loop, where .NET 4.6 JIT did not #449

Description

@FlsZen

Building the below code in VS Release mode results in different behavior when running the resulting binary in .NET 4.6 vs 4.7.

static void Main(string[] args)
{
    var c = new ChangeAFlagLater();
    while (!c.Flag) ;
}

class ChangeAFlagLater
{
    public ChangeAFlagLater()
    {
        Task.Delay(1000).ContinueWith(_ => Flag = true);
    }

    public bool Flag;
}

When running with 4.6, the while loop exits after the other thread changes Flag, but with .NET 4.7 it gets stuck looping forever. It's clear in the 4.7 disassembly that Flag isn't being checked again after entering the loop:

00007FF90031049F  movzx       eax,byte ptr [rsi+8]
00007FF9003104A3  test        eax,eax  
00007FF9003104A5  je          00007FF9003104A3  

Obviously, Flag should be marked volatile since it's being changed by another thread, and doing so prevents the infinite loop (je goes to 49F instead). Unfortunately, we found this in a production release running on a machine that had .NET 4.7 installed on it through Windows Updates, so it's a rather sneaky change in behavior. We hadn't noticed it yet on our dev machines because we mostly run in debug/without compiler optimizations.

Is this change in JIT considered a bug or is it a known issue or something?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions