Я хочу общаться с подпроцессом, используя канал, отличный от stdin, stdout и stderr.Я пытаюсь использовать Mono.Unix.UnixPipes.CreatePipes для этого.Тем не менее, я не могу найти никаких примеров, и мое лучшее предположение о том, как его использовать, не работает.Кажется, что дочерний процесс, который я создаю с помощью Process.Start, не может записать в унаследованный дескриптор файла.Я задаюсь вопросом, возможно ли это фактически не унаследовало ручку вообще.Вот мой (сокращенный) код:
using System;
using System.Diagnostics;
using System.IO;
using System.IO.Pipes;
using System.Threading;
using System.Collections.Generic;
using Mono.Unix;
class Program
{
static void Main(string[] args)
{
if (args.Length==0)
{
InvokeChildProcess(args);
}
else
{
RunAsChildProcess(args);
}
}
static int InvokeChildProcess(string[] aArgs)
{
var childToParentPipe = Mono.Unix.UnixPipes.CreatePipes();
var childToParentStream = childToParentPipe.Reading;
string childHandle = childToParentPipe.Writing.Handle.ToString();
var startInfo = new ProcessStartInfo(
System.Reflection.Assembly.GetExecutingAssembly().Location,
childHandle)
{
UseShellExecute = false,
};
Process childProcess = Process.Start(startInfo);
childToParentPipe.Writing.Close();
using (var reader = new StreamReader(childToParentStream))
{
Console.WriteLine("[PARENT] Waiting for child output...");
string output = reader.ReadToEnd();
Console.Write("[PARENT] Received output ({0} chars): ", output.Length);
Console.WriteLine(output);
Console.WriteLine("[PARENT] Waiting for child to exit...");
childProcess.WaitForExit();
Console.WriteLine("[PARENT] Saw child exit with code {0}.", childProcess.ExitCode);
return childProcess.ExitCode;
}
}
static void RunAsChildProcess(string[] args)
{
int handle=int.Parse(args[0]);
Console.WriteLine("[CHILD] Writing to file handle {0}.", handle);
var pipeToParent = new Mono.Unix.UnixStream(handle);
Thread.Sleep(2000);
using (var writer = new StreamWriter(pipeToParent))
{
writer.WriteLine("Message from child.");
writer.Flush();
Environment.Exit(123);
}
}
}
Вот вывод при запуске:
weeble@weeble-vm-oneiric32:~/dev$ mono MinimalPipeTest.exe
[PARENT] Waiting for child output...
[PARENT] Received output (0 chars):
[PARENT] Waiting for child to exit...
[CHILD] Writing to file handle 4.
Unhandled Exception: System.ArgumentException: Can not write to stream
at System.IO.StreamWriter..ctor (System.IO.Stream stream, System.Text.Encoding encoding, Int32 bufferSize) [0x00000] in <filename unknown>:0
at System.IO.StreamWriter..ctor (System.IO.Stream stream) [0x00000] in <filename unknown>:0
at (wrapper remoting-invoke-with-check) System.IO.StreamWriter:.ctor (System.IO.Stream)
at Program.RunAsChildProcess (System.String[] args) [0x00000] in <filename unknown>:0
at Program.Main (System.String[] args) [0x00000] in <filename unknown>:0
[ERROR] FATAL UNHANDLED EXCEPTION: System.ArgumentException: Can not write to stream
at System.IO.StreamWriter..ctor (System.IO.Stream stream, System.Text.Encoding encoding, Int32 bufferSize) [0x00000] in <filename unknown>:0
at System.IO.StreamWriter..ctor (System.IO.Stream stream) [0x00000] in <filename unknown>:0
at (wrapper remoting-invoke-with-check) System.IO.StreamWriter:.ctor (System.IO.Stream)
at Program.RunAsChildProcess (System.String[] args) [0x00000] in <filename unknown>:0
at Program.Main (System.String[] args) [0x00000] in <filename unknown>:0
[PARENT] Saw child exit with code 1.
weeble@weeble-vm-oneiric32:~/dev$
Этот пример был скомпилирован и запущен с Mono 2.10, как и в Ubuntu Oneiric.
Что я делаю не так?Как я могу гарантировать, что дочерний процесс сможет писать в канал?
EDIT - похоже, Process.Start действительно закрывает все файловые дескрипторы в дочернем процессеза исключением 0, 1 и 2. Смотрите здесь в CreateProcess:
https://github.com/mono/mono/blob/master/mono/io-layer/processes.c#L988
for (i = getdtablesize () - 1; i > 2; i--) {
close (i);
}
Я думаю, это означает, что я не могу использовать UnixPipes и Process.Start.Есть ли другой способ?