-
Notifications
You must be signed in to change notification settings - Fork 3.8k
Description
Steps to Reproduce
- Create an empty .net console app targeting net461
- Attempt to access any of the lockable properties from TermInfoDriver on multiple threads (example property I'm using is Background/ForegroundColor: )
mono/mcs/class/corlib/System/TermInfoDriver.cs
Lines 403 to 435 in cf24b9f
public ConsoleColor BackgroundColor { get { if (!inited) { Init (); } return bgcolor; } set { if (!inited) { Init (); } ChangeColor (setbgcolor, value); bgcolor = value; } } public ConsoleColor ForegroundColor { get { if (!inited) { Init (); } return fgcolor; } set { if (!inited) { Init (); } ChangeColor (setfgcolor, value); fgcolor = value; } }
Sample code to show exception
class Program
{
public static void Main(string[] args)
{
Parallel.Invoke(
() => { var x = Console.ForegroundColor; },
() => { Console.BackgroundColor = ConsoleColor.Black; }
);
}
}
- Build and run the application
Current Behavior
Occasionally, the application will run without an issue. However, most of the time an exception is thrown due to the behaviour I've described in this other thread here.
Expected Behavior
No exception should be thrown.
On which platforms did you notice this
[x] macOS
[x] Linux
[x] Windows
Version Used:
6.4.0
Stacktrace
Unhandled Exception:
System.AggregateException: One or more errors occurred. ---> System.DivideByZeroException: Attempted to divide by zero.
at System.TermInfoDriver.ChangeColor (System.String format, System.ConsoleColor color) [0x00016] in <filename unknown>:0
at System.TermInfoDriver.set_BackgroundColor (System.ConsoleColor value) [0x00011] in <filename unknown>:0
at System.ConsoleDriver.set_BackgroundColor (System.ConsoleColor value) [0x0001f] in <filename unknown>:0
at System.Console.set_BackgroundColor (System.ConsoleColor value) [0x00000] in <filename unknown>:0
at akka_test.Program+<>c.<Main>b__0_1 () [0x00001] in <filename unknown>:0
at System.Threading.Tasks.Task.InnerInvoke () [0x00012] in <filename unknown>:0
at System.Threading.Tasks.Task.Execute () [0x00016] in <filename unknown>:0
[MVID] 2320d006b1a64388aa1812d52f51bde3 4
[MVID] 7747cf446af449e194e4b4e70d85e773 0,1,2,3,5,6
--- End of inner exception stack trace ---
at System.Threading.Tasks.Task.FastWaitAll (System.Threading.Tasks.Task[] tasks) [0x0006e] in <filename unknown>:0
at System.Threading.Tasks.Parallel.Invoke (System.Threading.Tasks.ParallelOptions parallelOptions, System.Action[] actions) [0x0032e] in <filename unknown>:0
[MVID] 7747cf446af449e194e4b4e70d85e773 0,1
---> (Inner Exception #0) System.DivideByZeroException: Attempted to divide by zero.
at System.TermInfoDriver.ChangeColor (System.String format, System.ConsoleColor color) [0x00016] in <filename unknown>:0
at System.TermInfoDriver.set_BackgroundColor (System.ConsoleColor value) [0x00011] in <filename unknown>:0
at System.ConsoleDriver.set_BackgroundColor (System.ConsoleColor value) [0x0001f] in <filename unknown>:0
at System.Console.set_BackgroundColor (System.ConsoleColor value) [0x00000] in <filename unknown>:0
at akka_test.Program+<>c.<Main>b__0_1 () [0x00001] in <filename unknown>:0
at System.Threading.Tasks.Task.InnerInvoke () [0x00012] in <filename unknown>:0
at System.Threading.Tasks.Task.Execute () [0x00016] in <filename unknown>:0
[MVID] 2320d006b1a64388aa1812d52f51bde3 4
[MVID] 7747cf446af449e194e4b4e70d85e773 0,1,2,3,5,6<---
[ERROR] FATAL UNHANDLED EXCEPTION: System.AggregateException: One or more errors occurred. ---> System.DivideByZeroException: Attempted to divide by zero.
at System.TermInfoDriver.ChangeColor (System.String format, System.ConsoleColor color) [0x00016] in <filename unknown>:0
at System.TermInfoDriver.set_BackgroundColor (System.ConsoleColor value) [0x00011] in <filename unknown>:0
at System.ConsoleDriver.set_BackgroundColor (System.ConsoleColor value) [0x0001f] in <filename unknown>:0
at System.Console.set_BackgroundColor (System.ConsoleColor value) [0x00000] in <filename unknown>:0
at akka_test.Program+<>c.<Main>b__0_1 () [0x00001] in <filename unknown>:0
at System.Threading.Tasks.Task.InnerInvoke () [0x00012] in <filename unknown>:0
at System.Threading.Tasks.Task.Execute () [0x00016] in <filename unknown>:0
[MVID] 2320d006b1a64388aa1812d52f51bde3 4
[MVID] 7747cf446af449e194e4b4e70d85e773 0,1,2,3,5,6
--- End of inner exception stack trace ---
at System.Threading.Tasks.Task.FastWaitAll (System.Threading.Tasks.Task[] tasks) [0x0006e] in <filename unknown>:0
at System.Threading.Tasks.Parallel.Invoke (System.Threading.Tasks.ParallelOptions parallelOptions, System.Action[] actions) [0x0032e] in <filename unknown>:0
[MVID] 7747cf446af449e194e4b4e70d85e773 0,1
---> (Inner Exception #0) System.DivideByZeroException: Attempted to divide by zero.
at System.TermInfoDriver.ChangeColor (System.String format, System.ConsoleColor color) [0x00016] in <filename unknown>:0
at System.TermInfoDriver.set_BackgroundColor (System.ConsoleColor value) [0x00011] in <filename unknown>:0
at System.ConsoleDriver.set_BackgroundColor (System.ConsoleColor value) [0x0001f] in <filename unknown>:0
at System.Console.set_BackgroundColor (System.ConsoleColor value) [0x00000] in <filename unknown>:0
at akka_test.Program+<>c.<Main>b__0_1 () [0x00001] in <filename unknown>:0
at System.Threading.Tasks.Task.InnerInvoke () [0x00012] in <filename unknown>:0
at System.Threading.Tasks.Task.Execute () [0x00016] in <filename unknown>:0
[MVID] 2320d006b1a64388aa1812d52f51bde3 4
[MVID] 7747cf446af449e194e4b4e70d85e773 0,1,2,3,5,6<---
Process finished with exit code 1.
Notes
The core problem is that the lock on an uninitialised TermInfoDriver happens immediately upon accessing a property (get or set) and is released immediately before the initialisation process is complete. So, subsequent calls which happen concurrently will complete before any expected fields are present.
I'm not sure about the best way to fix this but it would be good to have this lock released after the initialisation process happens, but we would need to potentially try/catch the whole init block to account for exceptions.