dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
15.05k stars 4.69k forks source link

Console.ReadKey throws in unexpected circumstances #59059

Open JamesWTruher opened 3 years ago

JamesWTruher commented 3 years ago

Description

it appears that an exited application hangs on to console handles after it exits The application that I'm seeing in is the erlang program iex.

here's the code that shows off the issue.

using System;
using System.Diagnostics;
class Sample
{
    public static void Main()
    {
        Console.CancelKeyPress += new ConsoleCancelEventHandler(handler);
        ProcessStartInfo psi = new ProcessStartInfo("/usr/local/bin/iex");
        //psi.RedirectStandardInput = true;
        do
        {
            using(var p = Process.Start(psi)) {
                p?.WaitForExit();
            }
            Console.WriteLine("\nproc has ended.\npress a key to run it again - 'q' to stop");
        }
        while (Console.ReadKey(true).KeyChar != 'q');
    }

    protected static void handler(object? sender, ConsoleCancelEventArgs args)
    {
        args.Cancel = true;
    }
}

run the program and press CTRL-C twice (timing doesn't seem to matter here - quickly or slowly doesn't affect the outcome).

james@JamesiMac20 p025 % dotnet run
Erlang/OTP 24 [erts-12.0.3] [source] [64-bit] [smp:20:20] [ds:20:20:10] [async-threads:1] [jit] [dtrace]

Interactive Elixir (1.12.3) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> 
BREAK: (a)bort (A)bort with dump (c)ontinue (p)roc info (i)nfo
       (l)oaded (v)ersion (k)ill (D)b-tables (d)istribution
^C
proc has ended
press a key to run it again - 'q' to stop
Unhandled exception. System.IO.IOException: The process cannot access the file because it is being used by another process.
   at Interop.ThrowExceptionForIoErrno(ErrorInfo errorInfo, String path, Boolean isDirectory, Func`2 errorRewriter)
   at Interop.CheckIo(Int64 result, String path, Boolean isDirectory, Func`2 errorRewriter)
   at System.IO.StdInReader.ReadKey()
   at System.IO.StdInReader.ReadKey(Boolean& previouslyProcessed)
   at System.IO.SyncTextReader.ReadKey(Boolean& previouslyProcessed)
   at System.ConsolePal.ReadKey(Boolean intercept)
   at System.Console.ReadKey(Boolean intercept)
   at Sample.Main() in /Users/james/src/projects/signal/p025/Program.cs:line 18

Configuration

net6.0
osx-x64
Model Name: iMac
Model Identifier:   iMac20,1
Processor Name: 10-Core Intel Core i9
Processor Speed:    3.6 GHz
System Firmware Version:    1554.140.20.0.0 (iBridge: 18.16.14759.0.1,0)

Regression?

not sure

Other information

if the line which redirects StandardInput (or StandardOutput) is not commented out the error does not occur. i'm confused as to what's going on, the process has exited, but the error suggests that something is hanging on to a console handle.

ghost commented 3 years ago

Tagging subscribers to this area: @dotnet/area-system-console See info in area-owners.md if you want to be subscribed.

Issue Details
### Description it appears that an exited application hangs on to console handles after it exits The application that I'm seeing in is the `erlang` program `iex`. here's the code that shows off the issue. ```csharp using System; using System.Diagnostics; class Sample { public static void Main() { Console.CancelKeyPress += new ConsoleCancelEventHandler(handler); ProcessStartInfo psi = new ProcessStartInfo("/usr/local/bin/iex"); //psi.RedirectStandardInput = true; do { using(var p = Process.Start(psi)) { p?.WaitForExit(); } Console.WriteLine("\nproc has ended.\npress a key to run it again - 'q' to stop"); } while (Console.ReadKey(true).KeyChar != 'q'); } protected static void handler(object? sender, ConsoleCancelEventArgs args) { args.Cancel = true; } } ``` run the program and press `CTRL-C` twice (timing doesn't seem to matter here - quickly or slowly doesn't affect the outcome). ```output james@JamesiMac20 p025 % dotnet run Erlang/OTP 24 [erts-12.0.3] [source] [64-bit] [smp:20:20] [ds:20:20:10] [async-threads:1] [jit] [dtrace] Interactive Elixir (1.12.3) - press Ctrl+C to exit (type h() ENTER for help) iex(1)> BREAK: (a)bort (A)bort with dump (c)ontinue (p)roc info (i)nfo (l)oaded (v)ersion (k)ill (D)b-tables (d)istribution ^C proc has ended press a key to run it again - 'q' to stop Unhandled exception. System.IO.IOException: The process cannot access the file because it is being used by another process. at Interop.ThrowExceptionForIoErrno(ErrorInfo errorInfo, String path, Boolean isDirectory, Func`2 errorRewriter) at Interop.CheckIo(Int64 result, String path, Boolean isDirectory, Func`2 errorRewriter) at System.IO.StdInReader.ReadKey() at System.IO.StdInReader.ReadKey(Boolean& previouslyProcessed) at System.IO.SyncTextReader.ReadKey(Boolean& previouslyProcessed) at System.ConsolePal.ReadKey(Boolean intercept) at System.Console.ReadKey(Boolean intercept) at Sample.Main() in /Users/james/src/projects/signal/p025/Program.cs:line 18 ``` ### Configuration ```output net6.0 osx-x64 Model Name: iMac Model Identifier: iMac20,1 Processor Name: 10-Core Intel Core i9 Processor Speed: 3.6 GHz System Firmware Version: 1554.140.20.0.0 (iBridge: 18.16.14759.0.1,0) ``` ### Regression? not sure ### Other information if the line which redirects StandardInput (or StandardOutput) is not commented out the error does not occur. i'm confused as to what's going on, the process has exited, but the error suggests that _something_ is hanging on to a console handle.
Author: JamesWTruher
Assignees: -
Labels: `area-System.Console`, `untriaged`
Milestone: -
StephenBonikowsky commented 3 years ago

Related to https://github.com/PowerShell/PowerShell/issues/11215

jozkee commented 3 years ago

Not a regression, it reproes in 3.1 and 5.0, but definitely we need to take a look.