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 delegate Process
ProcessLauncher (ProcessStartInfo info
);
27 public class VirtualMachineManager
29 private delegate VirtualMachine
LaunchCallback (Process p
, Socket socket
);
30 private delegate VirtualMachine
ListenCallback (Socket dbg_sock
, Socket con_sock
);
32 internal VirtualMachineManager () {
35 public static VirtualMachine
LaunchInternal (Process p
, Socket socket
) {
36 Socket accepted
= null;
38 accepted
= socket
.Accept ();
43 Connection conn
= new Connection (accepted
);
45 VirtualMachine vm
= new VirtualMachine (p
, conn
);
47 if (p
.StartInfo
.RedirectStandardOutput
)
48 vm
.StandardOutput
= p
.StandardOutput
;
50 if (p
.StartInfo
.RedirectStandardError
)
51 vm
.StandardError
= p
.StandardError
;
53 conn
.EventHandler
= new EventHandler (vm
);
60 public static IAsyncResult
BeginLaunch (ProcessStartInfo info
, AsyncCallback callback
, LaunchOptions options
= null) {
62 throw new ArgumentNullException ("info");
64 Socket socket
= new Socket (AddressFamily
.InterNetwork
, SocketType
.Stream
, ProtocolType
.Tcp
);
65 socket
.Bind (new IPEndPoint (IPAddress
.Loopback
, 0));
67 IPEndPoint ep
= (IPEndPoint
) socket
.LocalEndPoint
;
69 // We need to inject our arguments into the psi
70 info
.Arguments
= string.Format ("{0} --debug --debugger-agent=transport=dt_socket,address={1}:{2}{3} {4}",
71 options
== null || !options
.Valgrind
? "" : info
.FileName
,
74 options
== null || options
.AgentArgs
== null ? "" : "," + options
.AgentArgs
,
77 if (options
!= null && options
.Valgrind
)
78 info
.FileName
= "valgrind";
81 if (options
!= null && options
.CustomProcessLauncher
!= null)
82 p
= options
.CustomProcessLauncher (info
);
84 p
= Process
.Start (info
);
86 p
.Exited
+= delegate (object sender
, EventArgs eargs
) {
90 LaunchCallback c
= new LaunchCallback (LaunchInternal
);
91 return c
.BeginInvoke (p
, socket
, callback
, socket
);
94 public static VirtualMachine
EndLaunch (IAsyncResult asyncResult
) {
95 if (asyncResult
== null)
96 throw new ArgumentNullException ("asyncResult");
98 if (!asyncResult
.IsCompleted
)
99 asyncResult
.AsyncWaitHandle
.WaitOne ();
101 AsyncResult
async = (AsyncResult
) asyncResult
;
102 LaunchCallback cb
= (LaunchCallback
) async.AsyncDelegate
;
103 return cb
.EndInvoke (asyncResult
);
106 public static VirtualMachine
Launch (ProcessStartInfo info
, LaunchOptions options
= null) {
107 return EndLaunch (BeginLaunch (info
, null, options
));
110 public static VirtualMachine
Launch (string[] args
, LaunchOptions options
= null) {
111 ProcessStartInfo pi
= new ProcessStartInfo ("mono");
112 pi
.Arguments
= String
.Join (" ", args
);
114 return Launch (pi
, options
);
117 public static VirtualMachine
ListenInternal (Socket dbg_sock
, Socket con_sock
) {
118 Socket con_acc
= null;
119 Socket dbg_acc
= null;
121 if (con_sock
!= null) {
123 con_acc
= con_sock
.Accept ();
124 } catch (Exception
) {
133 dbg_acc
= dbg_sock
.Accept ();
134 } catch (Exception
) {
135 if (con_sock
!= null) {
144 if (con_sock
!= null) {
145 con_sock
.Disconnect (false);
149 dbg_sock
.Disconnect (false);
152 Connection conn
= new Connection (dbg_acc
);
154 VirtualMachine vm
= new VirtualMachine (null, conn
);
156 if (con_acc
!= null) {
157 vm
.StandardOutput
= new StreamReader (new NetworkStream (con_acc
));
158 vm
.StandardError
= null;
161 conn
.EventHandler
= new EventHandler (vm
);
168 public static IAsyncResult
BeginListen (IPEndPoint dbg_ep
, AsyncCallback callback
) {
169 return BeginListen (dbg_ep
, null, callback
);
172 public static IAsyncResult
BeginListen (IPEndPoint dbg_ep
, IPEndPoint con_ep
, AsyncCallback callback
) {
173 Socket dbg_sock
= null;
174 Socket con_sock
= null;
176 dbg_sock
= new Socket (AddressFamily
.InterNetwork
, SocketType
.Stream
, ProtocolType
.Tcp
);
177 dbg_sock
.Bind (dbg_ep
);
178 dbg_sock
.Listen (1000);
180 if (con_ep
!= null) {
181 con_sock
= new Socket (AddressFamily
.InterNetwork
, SocketType
.Stream
, ProtocolType
.Tcp
);
182 con_sock
.Bind (con_ep
);
183 con_sock
.Listen (1000);
186 ListenCallback c
= new ListenCallback (ListenInternal
);
187 return c
.BeginInvoke (dbg_sock
, con_sock
, callback
, con_sock
?? dbg_sock
);
190 public static VirtualMachine
EndListen (IAsyncResult asyncResult
) {
191 if (asyncResult
== null)
192 throw new ArgumentNullException ("asyncResult");
194 if (!asyncResult
.IsCompleted
)
195 asyncResult
.AsyncWaitHandle
.WaitOne ();
197 AsyncResult
async = (AsyncResult
) asyncResult
;
198 ListenCallback cb
= (ListenCallback
) async.AsyncDelegate
;
199 return cb
.EndInvoke (asyncResult
);
202 public static VirtualMachine
Listen (IPEndPoint dbg_ep
, IPEndPoint con_ep
= null) {
203 return EndListen (BeginListen (dbg_ep
, con_ep
, null));
207 * Connect to a virtual machine listening at the specified address.
209 public static VirtualMachine
Connect (IPEndPoint endpoint
) {
210 if (endpoint
== null)
211 throw new ArgumentNullException ("endpoint");
213 Socket socket
= new Socket (AddressFamily
.InterNetwork
, SocketType
.Stream
, ProtocolType
.Tcp
);
214 socket
.Connect (endpoint
);
216 Connection conn
= new Connection (socket
);
218 VirtualMachine vm
= new VirtualMachine (null, conn
);
220 conn
.EventHandler
= new EventHandler (vm
);