Przeglądaj źródła

[System] When doing process redirect, use Console.OutputEncoding instead of Console.Out.Encoding. (#8438)

* [System] When doing process redirect, use Console.OutputEncoding instead of Console.Out.Encoding. Fixes #8417.

This change makes mono behave in the same way as dotnet, which uses Console.OutputEncoding instead of whatever Console.Out is.

* [System] Add regression test for #8417.
Rodrigo Kumpera 7 lat temu
rodzic
commit
3eaa5c2f48

+ 2 - 2
mcs/class/System/System.Diagnostics/Process.cs

@@ -801,7 +801,7 @@ namespace System.Diagnostics
 			if (startInfo.RedirectStandardOutput) {
 				MonoIO.Close (stdout_write, out error);
 
-				Encoding stdoutEncoding = startInfo.StandardOutputEncoding ?? Console.Out.Encoding;
+				Encoding stdoutEncoding = startInfo.StandardOutputEncoding ?? Console.OutputEncoding;
 
 				standardOutput = new StreamReader (new FileStream (stdout_read, FileAccess.Read, true, 8192), stdoutEncoding, true);
 			}
@@ -809,7 +809,7 @@ namespace System.Diagnostics
 			if (startInfo.RedirectStandardError) {
 				MonoIO.Close (stderr_write, out error);
 
-				Encoding stderrEncoding = startInfo.StandardErrorEncoding ?? Console.Out.Encoding;
+				Encoding stderrEncoding = startInfo.StandardErrorEncoding ?? Console.OutputEncoding;
 
 				standardError = new StreamReader (new FileStream (stderr_read, FileAccess.Read, true, 8192), stderrEncoding, true);
 			}

+ 5 - 0
mono/tests/Makefile.am

@@ -715,6 +715,11 @@ TESTS_CS_SRC += bug-60862.cs
 endif
 endif
 
+#maybe this test works on linux, not sure
+if HOST_DARWIN
+TESTS_CS_SRC += bug-8417.cs
+endif
+
 TESTS_IL_SRC=			\
 	tailcall/2.il	     \
 	tailcall/3.il	     \

+ 93 - 0
mono/tests/bug-8417.cs

@@ -0,0 +1,93 @@
+#define USE_REDIRECT
+using System;
+using System.IO;
+using System.Text;
+using System.Collections.Generic;
+using System.Diagnostics;
+
+namespace Example
+{
+	public static class EntryPoint 
+	{
+		public static bool RunProcess (string filename, string arguments, out int exitCode, out string stdout, bool capture_stderr = false)
+		{
+			var sb = new StringBuilder ();
+			var stdout_done = new System.Threading.ManualResetEvent (false);
+			var stderr_done = new System.Threading.ManualResetEvent (false);
+			using (var p = new Process ()) {
+				p.StartInfo.FileName = filename;
+				p.StartInfo.Arguments = arguments;
+				p.StartInfo.UseShellExecute = false;
+				p.StartInfo.RedirectStandardOutput = true;
+				p.StartInfo.RedirectStandardError = capture_stderr;
+
+				p.OutputDataReceived += (sender, e) => {
+					if (e.Data == null) {
+						stdout_done.Set ();
+					}
+					else {
+						lock (sb)
+							sb.AppendLine (e.Data);
+					}
+				};
+				if (capture_stderr) {
+					p.ErrorDataReceived += (sender, e) => {
+						if (e.Data == null) {
+							stderr_done.Set ();
+						}
+						else {
+							lock (sb)
+								sb.AppendLine (e.Data);
+						}
+					};
+				}
+				p.Start ();
+				p.BeginOutputReadLine ();
+				if (capture_stderr)
+					p.BeginErrorReadLine ();
+				p.WaitForExit ();
+				stdout_done.WaitOne (TimeSpan.FromSeconds (1));
+				if (capture_stderr)
+					stderr_done.WaitOne (TimeSpan.FromSeconds (1));
+				stdout = sb.ToString ();
+				exitCode = p.ExitCode;
+				return exitCode == 0;
+			}
+		}
+
+		static string RunRedirectOutput (Action action)
+		{
+			var existingOut = Console.Out;
+			var existingErr = Console.Error;
+
+			try {
+				using (StringWriter writer = new StringWriter ()) {
+
+#if USE_REDIRECT
+					Console.SetOut (writer);
+					Console.SetError (writer);
+#endif
+					action ();
+					return writer.ToString ();
+				}
+			}
+			finally {
+				Console.SetOut (existingOut);
+				Console.SetError (existingErr);
+			}
+		}
+
+		static void RunProcess ()
+		{
+			RunProcess ("/bin/echo", "who am i", out int exitCode, out string stdout);
+			Console.Write (stdout);
+		}
+
+		public static int Main ()
+		{
+			var str = RunRedirectOutput (RunProcess);
+			Console.WriteLine ("'{0}'", str);
+			return str == "who am i\n" ? 0 : 1;
+		}
+	}
+}