2 using System.Collections.Generic;
3 using System.Diagnostics;
6 using System.Net.Sockets;
7 using System.Runtime.Remoting.Messaging;
9 namespace Mono.Debugger.Soft
11 public class LaunchOptions {
12 public string AgentArgs {
16 public bool Valgrind {
20 public ProcessLauncher CustomProcessLauncher {
24 public TargetProcessLauncher CustomTargetProcessLauncher {
28 public delegate Process ProcessLauncher (ProcessStartInfo info);
29 public delegate ITargetProcess TargetProcessLauncher (ProcessStartInfo info);
32 public class VirtualMachineManager
34 private delegate VirtualMachine LaunchCallback (ITargetProcess p, ProcessStartInfo info, Socket socket);
35 private delegate VirtualMachine ListenCallback (Socket dbg_sock, Socket con_sock);
37 internal VirtualMachineManager () {
40 public static VirtualMachine LaunchInternal (Process p, ProcessStartInfo info, Socket socket)
42 return LaunchInternal (new ProcessWrapper (p), info, socket);
45 public static VirtualMachine LaunchInternal (ITargetProcess p, ProcessStartInfo info, Socket socket) {
46 Socket accepted = null;
48 accepted = socket.Accept ();
53 Connection conn = new Connection (accepted);
55 VirtualMachine vm = new VirtualMachine (p, conn);
57 if (info.RedirectStandardOutput)
58 vm.StandardOutput = p.StandardOutput;
60 if (info.RedirectStandardError)
61 vm.StandardError = p.StandardError;
63 conn.EventHandler = new EventHandler (vm);
70 public static IAsyncResult BeginLaunch (ProcessStartInfo info, AsyncCallback callback, LaunchOptions options = null) {
72 throw new ArgumentNullException ("info");
74 Socket socket = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
75 socket.Bind (new IPEndPoint (IPAddress.Loopback, 0));
77 IPEndPoint ep = (IPEndPoint) socket.LocalEndPoint;
79 // We need to inject our arguments into the psi
80 info.Arguments = string.Format ("{0} --debug --debugger-agent=transport=dt_socket,address={1}:{2}{3} {4}",
81 options == null || !options.Valgrind ? "" : info.FileName,
84 options == null || options.AgentArgs == null ? "" : "," + options.AgentArgs,
87 if (options != null && options.Valgrind)
88 info.FileName = "valgrind";
91 if (options != null && options.CustomProcessLauncher != null)
92 p = new ProcessWrapper (options.CustomProcessLauncher (info));
93 else if (options != null && options.CustomTargetProcessLauncher != null)
94 p = options.CustomTargetProcessLauncher (info);
96 p = new ProcessWrapper (Process.Start (info));
98 p.Exited += delegate (object sender, EventArgs eargs) {
102 LaunchCallback c = new LaunchCallback (LaunchInternal);
103 return c.BeginInvoke (p, info, socket, callback, socket);
106 public static VirtualMachine EndLaunch (IAsyncResult asyncResult) {
107 if (asyncResult == null)
108 throw new ArgumentNullException ("asyncResult");
110 if (!asyncResult.IsCompleted)
111 asyncResult.AsyncWaitHandle.WaitOne ();
113 AsyncResult async = (AsyncResult) asyncResult;
114 LaunchCallback cb = (LaunchCallback) async.AsyncDelegate;
115 return cb.EndInvoke (asyncResult);
118 public static VirtualMachine Launch (ProcessStartInfo info, LaunchOptions options = null) {
119 return EndLaunch (BeginLaunch (info, null, options));
122 public static VirtualMachine Launch (string[] args, LaunchOptions options = null) {
123 ProcessStartInfo pi = new ProcessStartInfo ("mono");
124 pi.Arguments = String.Join (" ", args);
126 return Launch (pi, options);
129 public static VirtualMachine ListenInternal (Socket dbg_sock, Socket con_sock) {
130 Socket con_acc = null;
131 Socket dbg_acc = null;
133 if (con_sock != null) {
135 con_acc = con_sock.Accept ();
136 } catch (Exception) {
145 dbg_acc = dbg_sock.Accept ();
146 } catch (Exception) {
147 if (con_sock != null) {
156 if (con_sock != null) {
157 con_sock.Disconnect (false);
161 dbg_sock.Disconnect (false);
164 Connection conn = new Connection (dbg_acc);
166 VirtualMachine vm = new VirtualMachine (null, conn);
168 if (con_acc != null) {
169 vm.StandardOutput = new StreamReader (new NetworkStream (con_acc));
170 vm.StandardError = null;
173 conn.EventHandler = new EventHandler (vm);
180 public static IAsyncResult BeginListen (IPEndPoint dbg_ep, AsyncCallback callback) {
181 return BeginListen (dbg_ep, null, callback);
184 public static IAsyncResult BeginListen (IPEndPoint dbg_ep, IPEndPoint con_ep, AsyncCallback callback) {
185 Socket dbg_sock = null;
186 Socket con_sock = null;
188 dbg_sock = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
189 dbg_sock.Bind (dbg_ep);
190 dbg_sock.Listen (1000);
192 if (con_ep != null) {
193 con_sock = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
194 con_sock.Bind (con_ep);
195 con_sock.Listen (1000);
198 ListenCallback c = new ListenCallback (ListenInternal);
199 return c.BeginInvoke (dbg_sock, con_sock, callback, con_sock ?? dbg_sock);
202 public static VirtualMachine EndListen (IAsyncResult asyncResult) {
203 if (asyncResult == null)
204 throw new ArgumentNullException ("asyncResult");
206 if (!asyncResult.IsCompleted)
207 asyncResult.AsyncWaitHandle.WaitOne ();
209 AsyncResult async = (AsyncResult) asyncResult;
210 ListenCallback cb = (ListenCallback) async.AsyncDelegate;
211 return cb.EndInvoke (asyncResult);
214 public static VirtualMachine Listen (IPEndPoint dbg_ep, IPEndPoint con_ep = null) {
215 return EndListen (BeginListen (dbg_ep, con_ep, null));
219 * Connect to a virtual machine listening at the specified address.
221 public static VirtualMachine Connect (IPEndPoint endpoint) {
222 if (endpoint == null)
223 throw new ArgumentNullException ("endpoint");
225 Socket socket = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
226 socket.Connect (endpoint);
228 Connection conn = new Connection (socket);
230 VirtualMachine vm = new VirtualMachine (null, conn);
232 conn.EventHandler = new EventHandler (vm);