Console.GetCursorPosition behaves oddly with multiple threads on WSL
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 35/100
- Issue type
- Bug
- Clarity
- Mostly clear
- Activity status
- Stale
- Tech stack
- csharp, ubuntu
- Domain
- cli, operating-systems
Research direction
Start with src/libraries/System.Console/src/System/ConsolePal.Unix.cs around the referenced GetCursorPosition logic, then run the supplied console program on Ubuntu 22.04 under WSL2 with .NET 8 or 9. Compare the interaction between Console.GetCursorPosition and Console.ReadLine across threads; done means the reported behavior is explained and corrected or reliably covered by a regression test.
Written by the indexing model from the issue text.
Description
Description
- According to https://github.com/dotnet/runtime/blob/6406b578b43646b0b1d348da00a32d2f61860cf7/src/libraries/System.Console/src/System/ConsolePal.Unix.cs#L455C1-L460C31, a call to
Console.GetCursorPositionfrom thread B can/will be blocked until a call toConsole.ReadLinein thread A completes. - However, when calling
Console.GetCursorPositionat least twice in the same iteration of aforloop in which thread A also callsConsole.ReadLine, this behavior no longer occurs and from then on B is able to callConsole.GetCursorPositionwithout being blocked.
Reproduction Steps
- Create a new console project, targeting .NET 8 or .NET 9.
- Run the following:
static void Main(string[] args)
{
Task.Run(() =>
{
while (true)
{
Console.WriteLine($"CursorPosition = {Console.GetCursorPosition()}");
Thread.Sleep(1000);
}
});
for (int i = 0; i < 10; i++)
{
string? input = Console.ReadLine();
if (i == 2)
{
Console.GetCursorPosition();
Console.GetCursorPosition();
}
}
}
Expected behavior
"CursorPosition = ..." should be printed every second, or remain blocked until the calls to Console.ReadLine() complete.
Actual behavior
In each iteration of the loop, nothing is printed until a string is read from Console.ReadLine(). However, once Console.GetCursorPosition() is called twice in the same iteration of the loop, the "CursorPosition = ..." line is printed every second as expected.
For example, CursorPosition = ... is only outputted after a new line is inputted, but after the GetCursorPosition lines are executed, the output continues without anything having been entered:
the
CursorPosition = (0, 2)
quick
CursorPosition = (0, 4)
brown
CursorPosition = (0, 6)
CursorPosition = (0, 7)
CursorPosition = (0, 8)
CursorPosition = (0, 9)
Moving one of the GetCursorPosition calls before the Console.ReadLine produces the same result as when both calls are done after the Console.ReadLine:
for (int i = 0; i < 10; i++)
{
Console.GetCursorPosition();
string? input = Console.ReadLine();
if (i == 2)
Console.GetCursorPosition();
}
Note the i == 2 can be any number (and the loop max is irrelevant), this is only to show behavior is consistent before GetCursorPosition is called a second time.
Regression?
No response
Known Workarounds
No response
Configuration
- Occurs in both .NET 8.0.403 and 9.0.100-preview.7.24407.12
- Running Ubuntu 22.04 via WSL2 on Windows 11.
- Same behavior in debug and release builds
- Outside of WSL, the task outputs every second as expected on both .NET versions.
Other information
No response
- Dominant language
- C#
- Stars
- 18.3k
- Forks
- 5.6k
- PR merge metrics
- PR metrics pending
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from dotnet/runtime
-
agentic-workflows untriaged
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
-
area-System.Reflection blocking-clean-ci-optional Known Build Error os-mac-os-x untriaged
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
-
area-CodeGen-coreclr untriaged
Difficulty 1/5 Under an hour Newbie friendliness 92/100
-
agentic-workflows untriaged
Difficulty 1/5 Under an hour Newbie friendliness 78/100
-
area-VM-meta-mono untriaged
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
-
:watch: Not Triaged 11.0 fundamentals/subsvc
Difficulty 2/5 1-3 hours Newbie friendliness 92/100
dotnet/AspNetCore.Docs#37699 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
SubtitleEdit/subtitleedit#15108 · 1 comment ·
-
area/docs-content Bug pulumi/docs
Difficulty 1/5 1-3 hours Newbie friendliness 94/100
-
Create parent directories only after the containment check in InstallHelper.TryExtractToDirectory Open
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
PowerShell/PSResourceGet#2056 ·