if (startInfo.RedirectStandardInput == true) {
MonoIO.Close (stdin_rd, out error);
- process.input_stream = new StreamWriter (new FileStream (stdin_wr, FileAccess.Write, true), Console.Out.Encoding);
+ process.input_stream = new StreamWriter (new MonoSyncFileStream (stdin_wr, FileAccess.Write, true, 8192), Console.Out.Encoding);
process.input_stream.AutoFlush = true;
}
if (startInfo.RedirectStandardOutput == true) {
MonoIO.Close (stdout_wr, out error);
- process.output_stream = new StreamReader (new FileStream (process.stdout_rd, FileAccess.Read, true), stdoutEncoding);
+ process.output_stream = new StreamReader (new MonoSyncFileStream (process.stdout_rd, FileAccess.Read, true, 8192), stdoutEncoding);
}
if (startInfo.RedirectStandardError == true) {
MonoIO.Close (stderr_wr, out error);
- process.error_stream = new StreamReader (new FileStream (process.stderr_rd, FileAccess.Read, true), stderrEncoding);
+ process.error_stream = new StreamReader (new MonoSyncFileStream (process.stderr_rd, FileAccess.Read, true, 8192), stderrEncoding);
}
process.StartExitCallbackIfNeeded ();
--- /dev/null
+//
+// System.IO.MonoSyncFileStream.cs: Synchronous FileStream with
+// asynchronous BeginRead/Write methods.
+//
+// Authors:
+// Robert Jordan (robertj@gmx.net)
+//
+// Copyright (C) 2007 Novell, Inc. (http://www.novell.com)
+//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Runtime.Remoting.Messaging;
+
+namespace System.IO
+{
+ internal class MonoSyncFileStream : FileStream
+ {
+ public MonoSyncFileStream (IntPtr handle, FileAccess access, bool ownsHandle, int bufferSize)
+ : base (handle, access, ownsHandle, bufferSize, false)
+ {
+ }
+
+ delegate void WriteDelegate (byte [] buffer, int offset, int count);
+
+ public override IAsyncResult BeginWrite (byte [] buffer, int offset, int count,
+ AsyncCallback cback, object state)
+ {
+ if (!CanWrite)
+ throw new NotSupportedException ("This stream does not support writing");
+
+ if (buffer == null)
+ throw new ArgumentNullException ("buffer");
+
+ if (count < 0)
+ throw new ArgumentOutOfRangeException ("count", "Must be >= 0");
+
+ if (offset < 0)
+ throw new ArgumentOutOfRangeException ("offset", "Must be >= 0");
+
+ WriteDelegate d = new WriteDelegate (this.Write);
+ return d.BeginInvoke (buffer, offset, count, cback, state);
+ }
+
+ public override void EndWrite (IAsyncResult asyncResult)
+ {
+ if (asyncResult == null)
+ throw new ArgumentNullException ("asyncResult");
+
+ AsyncResult ar = asyncResult as AsyncResult;
+ if (ar == null)
+ throw new ArgumentException ("Invalid IAsyncResult", "asyncResult");
+
+ WriteDelegate d = ar.AsyncDelegate as WriteDelegate;
+ if (d == null)
+ throw new ArgumentException ("Invalid IAsyncResult", "asyncResult");
+
+ d.EndInvoke (asyncResult);
+ }
+
+ delegate int ReadDelegate (byte [] buffer, int offset, int count);
+
+ public override IAsyncResult BeginRead (byte [] buffer, int offset, int count,
+ AsyncCallback cback, object state)
+ {
+ if (!CanRead)
+ throw new NotSupportedException ("This stream does not support reading");
+
+ if (buffer == null)
+ throw new ArgumentNullException ("buffer");
+
+ if (count < 0)
+ throw new ArgumentOutOfRangeException ("count", "Must be >= 0");
+
+ if (offset < 0)
+ throw new ArgumentOutOfRangeException ("offset", "Must be >= 0");
+
+ ReadDelegate d = new ReadDelegate (this.Read);
+ return d.BeginInvoke (buffer, offset, count, cback, state);
+ }
+
+ public override int EndRead (IAsyncResult asyncResult)
+ {
+ if (asyncResult == null)
+ throw new ArgumentNullException ("asyncResult");
+
+ AsyncResult ar = asyncResult as AsyncResult;
+ if (ar == null)
+ throw new ArgumentException ("Invalid IAsyncResult", "asyncResult");
+
+ ReadDelegate d = ar.AsyncDelegate as ReadDelegate;
+ if (d == null)
+ throw new ArgumentException ("Invalid IAsyncResult", "asyncResult");
+
+ return d.EndInvoke (asyncResult);
+ }
+
+ }
+}
//
// Authors:
// Gert Driesen (drieseng@users.sourceforge.net)
+// Robert Jordan <robertj@gmx.net>
//
// (C) 2007 Gert Driesen
//
using System;
using System.Diagnostics;
+using System.IO;
+using System.Text;
using NUnit.Framework;
Assert.IsNull (ex.InnerException, "#6");
}
}
+
+ [Test]
+ [Category ("NotDotNet")]
+ public void TestRedirectedOutputIsAsync ()
+ {
+ // Test requires cygwin, so we just bail out for now.
+ if (Path.DirectorySeparatorChar == '\\')
+ return;
+
+ // Create a SH script that emits "hello" after it slept for 2 secs.
+ string script = Path.GetTempFileName ();
+ TextWriter w = File.CreateText (script);
+ w.WriteLine ("sleep 2");
+ w.WriteLine ("echo hello");
+ w.Close ();
+
+ Process p = new Process ();
+ p.StartInfo = new ProcessStartInfo ("/bin/sh", script);
+ p.StartInfo.RedirectStandardOutput = true;
+ p.StartInfo.UseShellExecute = false;
+ p.Start ();
+
+ Stream stdout = p.StandardOutput.BaseStream;
+
+ byte [] buffer = new byte [200];
+
+ // start async Read operation
+ DateTime start = DateTime.Now;
+ stdout.BeginRead (buffer, 0, buffer.Length,
+ new AsyncCallback (Read), stdout);
+
+ Assert.IsTrue ((DateTime.Now - start).TotalMilliseconds < 1000, "#01 BeginRead was not async");
+ p.WaitForExit ();
+ File.Delete (script);
+
+ Assert.AreEqual ("hello", Encoding.Default.GetString (buffer, 0, 5), "#02");
+ }
+
+ void Read (IAsyncResult ar)
+ {
+ Stream stm = (Stream) ar.AsyncState;
+ stm.EndRead (ar);
+ }
}
}