Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Console.ForegroundColor deadlocks Console on OSX #34197

Closed
lduchosal opened this issue Mar 20, 2020 · 4 comments · Fixed by #34297
Closed

Console.ForegroundColor deadlocks Console on OSX #34197

lduchosal opened this issue Mar 20, 2020 · 4 comments · Fixed by #34297
Labels
area-System.Console bug os-linux Linux OS (any supported distro) os-mac-os-x macOS aka OSX tenet-reliability Reliability/stability related issue (stress, load problems, etc.)
Milestone

Comments

@lduchosal
Copy link

Description

The console is locked with the following conditions :

Thread dotnet/core#1. Console.WriteLine
Thread dotnet/core#2. Console.ForegroundColor locks and never returns
Thread dotnet/core#3. Console.ReadLine is locked and never returns

Problem on NET Core OSX version 3.1.200. Works on Windows x64.

Expected

Thread dotnet/core#1. Console.WriteLine
Thread dotnet/core#2. Console.ForegroundColor returns
Thread dotnet/core#3. Console.ReadLine returns

Code to reproduce

`

class Program
{
    static void Main(string[] args)
    {

        // remove this line to workaround the bug
        Console.WriteLine(@"Program.Main, try a few times to reproduce the issue");

        var wait1 = new AutoResetEvent(false);
        var wait2 = new AutoResetEvent(false);
        
        Task.Factory.StartNew(() =>
        {
            Console.ForegroundColor = ConsoleColor.Green;
            Console.WriteLine("never happens");
            Console.ResetColor();
            
            wait1.Set();
        });

        Task.Factory.StartNew(() =>
        {
            var line = Console.ReadLine();
            Console.WriteLine("never happens");
            wait2.Set();
        });

        WaitHandle.WaitAll(new[] {wait1, wait2});
        Console.WriteLine("never happens");

    }
}

`

environnement

SDK .NET Core (reflétant tous les global.json) :
Version: 3.1.200
Commit: c5123d973b

Environnement d'exécution :
OS Name: Mac OS X
OS Version: 10.15
OS Platform: Darwin
RID: osx.10.15-x64
Base Path: /usr/local/share/dotnet/sdk/3.1.200/

Host (useful for support):
Version: 3.1.2
Commit: 916b5cba26

.NET Core SDKs installed:
3.1.200 [/usr/local/share/dotnet/sdk]

.NET Core runtimes installed:
Microsoft.AspNetCore.App 3.1.2 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.NETCore.App 3.1.2 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]

To install additional .NET Core runtimes or SDKs:
https://aka.ms/dotnet-download

Thanks for your help.

@scalablecory scalablecory transferred this issue from dotnet/core Mar 27, 2020
@Dotnet-GitSync-Bot Dotnet-GitSync-Bot added area-System.Console untriaged New issue has not been triaged by the area owner labels Mar 27, 2020
@scalablecory scalablecory added bug os-mac-os-x macOS aka OSX labels Mar 27, 2020
@tmds
Copy link
Member

tmds commented Mar 28, 2020

@danmosemsft I had a look at this issue.

There is a deadlock happening here between Console.Out and Console.InternalSyncObject.

Task setting Console.ForegroundColor:

-> lock (Console.InternalSyncObject)
System.Threading.Monitor.ReliableEnter(System.Object, Boolean ByRef)
System.Threading.LazyInitializer.EnsureInitializedCore[[System.__Canon, System.Private.CoreLib]](System.__Canon ByRef, System.Object ByRef, System.Func`1<System.__Canon>)
System.Threading.LazyInitializer.EnsureInitialized[[System.__Canon, System.Private.CoreLib]](System.__Canon ByRef, System.Object ByRef, System.Func`1<System.__Canon>)
System.Console.get_IsOutputRedirected()

System.ConsolePal.WriteResetColorString()
-> lock (Console.Out)
System.ConsolePal.RefreshColors(System.ConsoleColor ByRef, System.ConsoleColor)

System.Console.set_ForegroundColor(System.ConsoleColor)

Task calling Console.ReadLine:

-> lock (Console.Console.Out)
System.Threading.Monitor.Enter(System.Object, Boolean ByRef)
System.ConsolePal.EnsureInitializedCore()
System.ConsolePal.get_StdInReader()
System.ConsolePal.GetOrCreateReader()
System.Console+<>c.<get_In>b__14_0()

-> lock (InternalSyncObject)
System.Threading.LazyInitializer.EnsureInitializedCore[[System.__Canon, System.Private.CoreLib]](System.__Canon ByRef, System.Object ByRef, System.Func`1<System.__Canon>)
System.Threading.LazyInitializer.EnsureInitialized[[System.__Canon, System.Private.CoreLib]](System.__Canon ByRef, System.Object ByRef, System.Func`1<System.__Canon>)
System.Console.get_In()

System.Console.ReadLine()

@stephentoub stephentoub removed the untriaged New issue has not been triaged by the area owner label Mar 28, 2020
@stephentoub stephentoub added this to the 5.0 milestone Mar 28, 2020
@stephentoub stephentoub added the os-linux Linux OS (any supported distro) label Mar 28, 2020
@tmds
Copy link
Member

tmds commented Mar 30, 2020

Probably we want to continue EnsureInitializedCore when someone gets Console.In.

EnsureInitializedCore locks Console.Out because it writes to stdout.

So the fix should be to ensure no-one holds Console.Out lock while performing LazyInitializer.EnsureInitialized.

I'll look into making this change.

@tmds
Copy link
Member

tmds commented Mar 30, 2020

So the fix should be to ensure no-one holds Console.Out lock while performing LazyInitializer.EnsureInitialized.

Actually, the user may also hold Console.Out and trigger LazyInitializer.EnsureInitialized. So there is no way to avoid that.

We can't call EnsureInitializedCore under LazyInitializer.EnsureInitialized.

@stephentoub
Copy link
Member

stephentoub commented Mar 30, 2020

From a quick peek, most of the lazily-initialized members could be done optimistically, without a lock and just with a compare-exchange to substitute in the results. A few of them might be more complicated, though.

@marklio marklio added the tenet-reliability Reliability/stability related issue (stress, load problems, etc.) label Mar 31, 2020
@ghost ghost locked as resolved and limited conversation to collaborators Dec 10, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-System.Console bug os-linux Linux OS (any supported distro) os-mac-os-x macOS aka OSX tenet-reliability Reliability/stability related issue (stress, load problems, etc.)
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants