Permalink
Browse files

Flesh out ChildProcess interface, not fully functional yet

  • Loading branch information...
1 parent e9b2d0a commit 24391c604602bace47315f0dffadeb27d2f86597 @kersny committed Aug 20, 2011
Showing with 73 additions and 155 deletions.
  1. +5 −4 src/Libuv.Tests/webserver.cs
  2. +51 −55 src/Libuv/ChildProcess.cs
  3. +13 −95 src/Libuv/PipeSocket.cs
  4. +4 −1 src/Libuv/TcpSocket.cs
@@ -13,7 +13,7 @@ class webserver {
static int clientcount = 0;
static void Main ()
{
- var endpoint = new IPEndPoint(new IPAddress(new byte[] { 127, 0, 0, 1}), 8080);
+ var endpoint = new IPEndPoint(new IPAddress(new byte[] { 127, 0, 0, 1}), 8081);
uv_init();
var watch = new PrepareWatcher(() => {
@@ -54,7 +54,7 @@ static void Main ()
socket.Close();
}
Console.WriteLine("Pipe Client Connected");
- socket.Stream.OnData += (data) => {
+ socket.Stream.OnRead += (data) => {
Console.WriteLine("Pipe Data Recieved: {0}", System.Text.Encoding.ASCII.GetString(data, 0, data.Length));
socket.Stream.Write(data, data.Length);
};
@@ -65,7 +65,7 @@ static void Main ()
pipeserver.Listen("libuv-csharp");
var pipeclient = new PipeSocket();
pipeclient.Connect("libuv-csharp", () => {
- pipeclient.Stream.OnData += (data) => {
+ pipeclient.Stream.OnRead += (data) => {
Console.WriteLine("Pipe Client Recieved: {0}", System.Text.Encoding.ASCII.GetString(data, 0, data.Length));
watch.Stop();
watch.Dispose();
@@ -95,7 +95,8 @@ static void Main ()
// after.Stop();
});
every.Start();
- var cp = new ChildProcess();
+ var cp = new ChildProcess("ls");
+ cp.Spawn();
uv_run();
}
}
View
@@ -1,6 +1,7 @@
using System;
using System.Text;
using System.IO;
+using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace Libuv {
@@ -11,7 +12,7 @@ public struct uv_process_options_t {
public uv_exit_cb exit_cb;
public string file;
public IntPtr[] args;
- public string[] env;
+ public IntPtr[] env;
public string cwd;
public int windows_verbatim_arguments;
@@ -24,46 +25,10 @@ public class ChildProcess {
public static extern int uv_spawn(IntPtr process, uv_process_options_t options);
[DllImport ("uv")]
public static extern int uv_process_kill(IntPtr process, int signum);
- [DllImport("uv")]
- internal static extern int uv_pipe_init(IntPtr prepare);
[DllImport ("uv")]
- public static extern int uv_close(IntPtr process, uv_close_cb cb);
+ public static extern int uv_pipe_init(IntPtr pipe);
[DllImport ("uv")]
- internal static extern int uv_read_start(IntPtr stream, uv_alloc_cb alloc_cb, uv_read_cb read);
- static uv_buf_t static_alloc(IntPtr pipe, IntPtr size)
- {
- uv_buf_t buf;
- buf.data = Marshal.AllocHGlobal((int)size);
- #if __MonoCS__
- buf.len = size;
- #else
- buf.len = (ulong)size;
- #endif
- return buf;
- }
- static void static_read(IntPtr stream, IntPtr nread, uv_buf_t buf)
- {
- int size = (int)nread;
- if (size < 0) {
- if ((int)buf.data != 0)
- Marshal.FreeHGlobal(buf.data);
- //IntPtr shutdown = Marshal.AllocHGlobal(Sizes.ShutdownTSize);
- //uv_shutdown(shutdown, stream, after_shutdown);
- return;
- }
- if (size == 0) {
- Marshal.FreeHGlobal(buf.data);
- return;
- }
- byte[] data = new byte[size];
- Marshal.Copy(buf.data, data, 0, size);
- Console.WriteLine("FROM PROC: {0}", System.Text.Encoding.ASCII.GetString(data));
- //var handle = (uv_handle_t)Marshal.PtrToStructure(stream, typeof(uv_handle_t));
- //var instance = GCHandle.FromIntPtr(handle.data);
- //var watcher_instance = (PipeSocket)instance.Target;
- //watcher_instance.HandleRead(data, size);
- Marshal.FreeHGlobal(buf.data);
- }
+ public static extern int uv_close(IntPtr process, uv_close_cb cb);
static void static_exit(IntPtr handle, int exit_status, int term_signal)
{
uv_close(handle, static_close);
@@ -72,25 +37,56 @@ static void static_close(IntPtr handle)
{
Marshal.FreeHGlobal(handle);
}
- uv_process_options_t options;
- public ChildProcess()
+ public string File { get; set; }
+ public string CurrentWorkingDirectory { get; set; }
+ public List<string> Environment { get; private set; }
+ public List<string> Arguments { get; private set; }
+ private IntPtr _handle;
+ public UVStream StdOut;
+ public UVStream StdErr;
+ private IntPtr _stdout;
+ private IntPtr _stderr;
+ //public event Action<string, string> OnExit;
+ //private void HandleExit(string stdout, string stderr);
+
+ public ChildProcess(string command)
+ {
+ this.File = command;
+ this.CurrentWorkingDirectory = Directory.GetCurrentDirectory();
+ this._stdout = Marshal.AllocHGlobal(Sizes.PipeT);
+ uv_pipe_init(_stdout);
+ this.StdOut = new UVStream(_stdout);
+ this._stderr = Marshal.AllocHGlobal(Sizes.PipeT);
+ uv_pipe_init(_stdout);
+ this.StdOut = new UVStream(_stdout);
+ this._handle = Marshal.AllocHGlobal(Sizes.ProcessT);
+ }
+ public void Spawn()
{
- IntPtr stdout = Marshal.AllocHGlobal(Sizes.PipeT);
- uv_pipe_init(stdout);
- IntPtr process = Marshal.AllocHGlobal(Sizes.ProcessT);
- var pwd = Directory.GetCurrentDirectory();
- pwd = Path.Combine(pwd, "t");
- options = new uv_process_options_t();
+ var options = new uv_process_options_t();
options.exit_cb = static_exit;
- options.file = pwd;
- var args = new IntPtr[3];
- args[0] = Marshal.StringToHGlobalAuto(pwd);
- args[1] = Marshal.StringToHGlobalAuto("t");
- args[2] = IntPtr.Zero;
+ options.file = this.File;
+ var args = new IntPtr[Arguments.Count + 3];
+ args[0] = Marshal.StringToHGlobalAuto(this.CurrentWorkingDirectory);
+ args[1] = Marshal.StringToHGlobalAuto(this.File);
+ args[args.Length - 1] = IntPtr.Zero;
+ for (int i = 0; i < Arguments.Count; i++)
+ {
+ args[i + 2] = Marshal.StringToHGlobalAuto(Arguments[i]);
+ }
options.args = args;
- options.stdout_stream = stdout;
- uv_spawn(process, options);
- uv_read_start(stdout, static_alloc, static_read);
+ var env = new IntPtr[Environment.Count + 1];
+ env[Environment.Count - 1] = IntPtr.Zero;
+ for (int i = 0; i < Environment.Count; i++)
+ {
+ env[i] = Marshal.StringToHGlobalAuto(Environment[i]);
+ }
+ options.env = env;
+ options.stdout_stream = _stdout;
+ options.stderr_stream = _stderr;
+ Util.CheckError(uv_spawn(_handle, options));
+ StdOut.ReadStart();
+ StdErr.ReadStart();
}
}
}
View
@@ -4,84 +4,37 @@
namespace Libuv {
public class PipeSocket {
- static uv_buf_t alloc_cb(IntPtr pipe, IntPtr size)
- {
- uv_buf_t buf;
- buf.data = Marshal.AllocHGlobal((int)size);
- #if __MonoCS__
- buf.len = size;
- #else
- buf.len = (ulong)size;
- #endif
- return buf;
- }
- static void unmanaged_read_cb(IntPtr stream, IntPtr nread, uv_buf_t buf)
- {
- int size = (int)nread;
- if (size < 0) {
- if ((int)buf.data != 0)
- Marshal.FreeHGlobal(buf.data);
- IntPtr shutdown = Marshal.AllocHGlobal(Sizes.ShutdownT);
- uv_shutdown(shutdown, stream, after_shutdown);
- return;
- }
- if (size == 0) {
- Marshal.FreeHGlobal(buf.data);
- return;
- }
- byte[] data = new byte[size];
- Marshal.Copy(buf.data, data, 0, size);
- var handle = (uv_handle_t)Marshal.PtrToStructure(stream, typeof(uv_handle_t));
- var instance = GCHandle.FromIntPtr(handle.data);
- var watcher_instance = (PipeSocket)instance.Target;
- watcher_instance.HandleRead(data, size);
- Marshal.FreeHGlobal(buf.data);
- }
+ public UVStream Stream { get; private set; }
static void unmanaged_connect_cb(IntPtr connection, int status)
{
- if (status != 0) {
- throw new Exception(uv_strerror(uv_last_error()));
- }
+ Util.CheckError(status);
var tmp = (uv_connect_t)Marshal.PtrToStructure(connection, typeof(uv_connect_t));
var handle = (uv_handle_t)Marshal.PtrToStructure(tmp.handle, typeof(uv_handle_t));
var instance = GCHandle.FromIntPtr(handle.data);
- var watcher_instance = (PipeSocket)instance.Target;
- watcher_instance.HandleConnect();
- uv_read_start(tmp.handle, alloc_cb, unmanaged_read_cb);
- }
- static void after_shutdown(IntPtr shutdown, int status)
- {
- // It'd be very difficult to get handle out of req
- // So we'll store it in data & cast to uv_req_t
- uv_shutdown_t tmp = (uv_shutdown_t)Marshal.PtrToStructure(shutdown, typeof(uv_shutdown_t));
- uv_close(tmp.handle, on_close);
- Marshal.FreeHGlobal(shutdown);
+ var socket_instance = (PipeSocket)instance.Target;
+ socket_instance.Stream = new UVStream(socket_instance._handle);
+ socket_instance.Stream.ReadStart();
+ socket_instance.HandleConnect();
}
static void on_close(IntPtr socket)
{
+ /*
var handle = (uv_handle_t)Marshal.PtrToStructure(socket, typeof(uv_handle_t));
var instance = GCHandle.FromIntPtr(handle.data);
var watcher_instance = (PipeSocket)instance.Target;
//dont think this is what should happen here
watcher_instance.me.Free();
Marshal.FreeHGlobal(socket);
- }
- static void after_write(IntPtr write_req, int status)
- {
- var req = (uv_req_t)Marshal.PtrToStructure(write_req, typeof(uv_req_t));
- //var handle = GCHandle.FromIntPtr(req.data);
- //handle.Free();
- Marshal.FreeHGlobal(write_req);
+ */
}
private IntPtr _handle;
- public event Action<byte[]> OnData;
public event Action OnConnect;
private GCHandle me;
private IntPtr connection;
public PipeSocket()
{
this._handle = Marshal.AllocHGlobal(Sizes.PipeT);
- uv_pipe_init(this._handle);
+ Util.CheckError(uv_pipe_init(this._handle));
var handle = (uv_handle_t)Marshal.PtrToStructure(this._handle, typeof(uv_handle_t));
this.me = GCHandle.Alloc(this);
handle.data = GCHandle.ToIntPtr(this.me);
@@ -91,37 +44,19 @@ public PipeSocket()
}
public void Connect(string path, Action OnConnect)
{
- uv_pipe_connect(this.connection, this._handle, path, unmanaged_connect_cb);
+ Util.CheckError(uv_pipe_connect(this.connection, this._handle, path, unmanaged_connect_cb));
this.OnConnect += OnConnect;
}
public PipeSocket(IntPtr ServerHandle)
{
this._handle = Marshal.AllocHGlobal(Sizes.PipeT);
- uv_pipe_init(this._handle);
- uv_accept(ServerHandle, this._handle);
+ Util.CheckError(uv_pipe_init(this._handle));
+ Util.CheckError(uv_accept(ServerHandle, this._handle));
var handle = (uv_handle_t)Marshal.PtrToStructure(this._handle, typeof(uv_handle_t));
this.me = GCHandle.Alloc(this);
handle.data = GCHandle.ToIntPtr(this.me);
Marshal.StructureToPtr(handle, this._handle, true);
- uv_read_start(this._handle, alloc_cb, unmanaged_read_cb);
- }
- public void Write(byte[] data, int length)
- {
- IntPtr write_request = Marshal.AllocHGlobal(Sizes.WriteT);
- var dataptrhandle = GCHandle.Alloc(data, GCHandleType.Pinned);
- // This is not being freed, which needs to be fixed
- IntPtr dat = dataptrhandle.AddrOfPinnedObject();
- uv_buf_t[] buf = new uv_buf_t[1];
- buf[0].data = dat;
- #if __MonoCS__
- buf[0].len = (IntPtr)length;
- #else
- buf[0].len = (ulong)length;
- #endif
- var req = (uv_req_t)Marshal.PtrToStructure(write_request, typeof(uv_req_t));
- req.data = dat;
- Marshal.StructureToPtr(req, write_request, true);
- uv_write(write_request, this._handle, buf, 1, after_write);
+ this.Stream = new UVStream(this._handle);
}
private void HandleConnect()
{
@@ -130,13 +65,6 @@ private void HandleConnect()
OnConnect();
}
}
- private void HandleRead(byte[] data, int nread)
- {
- if (OnData != null)
- {
- OnData(data);
- }
- }
public void Close()
{
uv_close(this._handle, on_close);
@@ -146,18 +74,8 @@ public void Close()
[DllImport ("uv")]
internal static extern int uv_accept(IntPtr socket, IntPtr stream);
[DllImport ("uv")]
- internal static extern int uv_read_start(IntPtr stream, uv_alloc_cb alloc_cb, uv_read_cb read);
- [DllImport ("uv")]
- internal static extern int uv_write(IntPtr req, IntPtr handle, uv_buf_t[] bufs, int bufcnt, uv_write_cb cb);
- [DllImport ("uv")]
- internal static extern int uv_shutdown(IntPtr shutdown, IntPtr handle, uv_shutdown_cb cb);
- [DllImport ("uv")]
internal static extern int uv_close(IntPtr handle, uv_close_cb cb);
[DllImport ("uv")]
internal static extern int uv_pipe_connect(IntPtr connect, IntPtr tcp_handle, string path, uv_connect_cb cb);
- [DllImport ("uv")]
- public static extern uv_err_t uv_last_error();
- [DllImport ("uv")]
- public static extern string uv_strerror(uv_err_t err);
}
}
View
@@ -12,17 +12,20 @@ static void unmanaged_connect_cb(IntPtr connection, int status)
var handle = (uv_handle_t)Marshal.PtrToStructure(tmp.handle, typeof(uv_handle_t));
var instance = GCHandle.FromIntPtr(handle.data);
var socket_instance = (TcpSocket)instance.Target;
- socket_instance.HandleConnect();
socket_instance.Stream = new UVStream(socket_instance._handle);
+ socket_instance.Stream.ReadStart();
+ socket_instance.HandleConnect();
}
static void on_close(IntPtr socket)
{
+ /*
var handle = (uv_handle_t)Marshal.PtrToStructure(socket, typeof(uv_handle_t));
var instance = GCHandle.FromIntPtr(handle.data);
var watcher_instance = (TcpSocket)instance.Target;
//dont think this is what should happen here
watcher_instance.me.Free();
Marshal.FreeHGlobal(socket);
+ */
}
private IntPtr _handle;
public event Action OnConnect;

0 comments on commit 24391c6

Please sign in to comment.