Sdk: Console.Write() doesn't show output until a newline

Created on 29 Apr 2016  路  14Comments  路  Source: dotnet/sdk

(from dotnet/corefx#8183 by @omajid)

On RHEL 7, Console.Write()'s output does not get displayed until a newline is used (or the program exits).

If you run the following application, you don't see anything as the output until 10 seconds have passed. Then all of "HelloWorld!" appears at once.

 public static void Main(string[] args)
 {
     Console.Write("Hello World");
     Console.Out.Flush();
     Task.Delay(10000).Wait();
     Console.WriteLine("!");
 }

Console applications that do input/output may use a style like the following:

public static void Main(string[] args)
{
    Console.Write("Name: ");
    var name = Console.ReadLine();
    Console.WriteLine("Your name is '" + name + "'.");
}

This doesn't work for me. You get no output at all at first. If you type in something (say "Foo") and hit ENTER, then you see all of the output at once:

Name: Foo
Your name is 'Foo'.

If you don't hit enter, then it seems like the application has hung. A Console.Out.Flush() doesn't fix this, as in the following:

public static void Main(string[] args)
{
    Console.Write("Name: ");
    Console.Out.Flush();
    var name = Console.ReadLine();
    Console.WriteLine("Your name is '" + name + "'.");
}

I ran all the test cases while ssh'ed into the RHEL 7 VM.

$ dotnet --version
1.0.0-rc2-002538
Bug

Most helpful comment

The customer experience is pretty bad, and it seems like most folks will hit this, so I'd consider it.

All 14 comments

Like dotnet/sdk#5926, this is only a problem when invoking the program via dotnet run. If you invoke the MSIL directly, there are no issues.

This is because our StreamForwarder that takes output from the real process and forwards it to the process running dotnet run only writes when it hits a newline:

https://github.com/dotnet/cli/blob/rel/1.0.0/src/Microsoft.DotNet.Cli.Utils/StreamForwarder.cs#L70

/cc @brthor @anurse

This is to prevent interleaving characters in streams that are forwarded and is by design.

The plan was to remove the need for streamforwarder altogether but the work hasn't happened yet.

IIRC The streamforwarder's most important function was allowing us to simultaneously capture and forward the output so we could summarize csc diagnostics for builds of a multiple project at the end of dotnet build.
When we did not buffer by line, the output would become chaotic and unreadable.

Bringing over some context from dotnet/sdk#5926, this also causes console.readline not to display output until a newline is entered.

@ellismg do you see this as an RC2 blocker? The Console.Write issue has an easy workaround, but the Console.Readline UX issue makes me think we should consider taking this for RC2.

The customer experience is pretty bad, and it seems like most folks will hit this, so I'd consider it.

Maybe when we are running dotnet run, we don't batch up the lines in StreamForwarder. This makes sense because dotnet run can only run a single app at a time, thus the output will only be interleaved if the actual app interleaves the output.

But when used elsewhere, we batch up the lines and only write out on \n.

Thoughts?

I think for dotnet run we can remove the stream forwarder altogether, why do we need to capture the output?

In order to write it to the screen so the user can read it.

I should've been more clear.

Using the corefx apis let's us redirect or capture the stdout/stderr streams. The stream forwarder exists so we can do both as I understand it, but we capture with the corefx apis.

We don't need to capture child process output in dotnet run so why don't we forward with corefx apis and remove stream forwarder interaction altogether in dotnet run

Is this issue somehow specific to RHEL 7 [per title] or it exists everywhere?

I'm pretty sure we don't ever need to capture and forward anymore... Forwarding is automatically handled by the CoreFX APIs, there's no need to capture and write it yourself. We only needed things like this when we captured AND forwarded, which I don't think we do anymore.

@piotrpMSFT This exists everywhere.

@anurse We still need it for build no?

@brthor Nothing I know of in build needs to both capture and forward. When we launch csc we capture, but don't forward. Everything else is forwarded.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

darrensimio picture darrensimio  路  3Comments

joffreykern picture joffreykern  路  3Comments

pranavkm picture pranavkm  路  3Comments

gkhanna79 picture gkhanna79  路  3Comments

natemcmaster picture natemcmaster  路  3Comments