2 using System
.Collections
.Generic
;
3 using System
.Diagnostics
;
4 using System
.Runtime
.InteropServices
;
7 using System
.Threading
;
9 using System
.Net
.Sockets
;
12 using Mono
.Unix
.Native
;
17 * Represents a running mono virtual machine.
19 public class VirtualMachine
{
23 public VirtualMachine (long pid
) {
24 // FIXME: Check for unix
34 public bool IsCurrent
{
36 return pid
== Syscall
.getpid ();
40 public string[] GetCommandLine () {
41 return File
.OpenText ("/proc/" + pid
+ "/cmdline").ReadToEnd ().Split ('\0');
44 public string GetWorkingDirectory () {
45 return UnixPath
.ReadLink ("/proc/" + pid
+ "/cwd");
49 * Return the list of running mono vms owned by the current user. The
50 * result includes the current vm too.
52 public static List
<VirtualMachine
> GetVirtualMachines () {
53 PerformanceCounterCategory p
= new PerformanceCounterCategory (".NET CLR JIT");
54 string[] machines
= p
.GetInstanceNames ();
56 var res
= new List
<VirtualMachine
> ();
58 foreach (string s
in machines
) {
59 // The names are in the form 'pid/name'
60 int pos
= s
.IndexOf ('/');
62 res
.Add (new VirtualMachine (Int32
.Parse (s
.Substring (0, pos
))));
68 * Loads the specific agent assembly into this vm.
70 public void Attach (string agent
, string args
) {
71 string user
= UnixUserInfo
.GetRealUser ().UserName
;
73 // Check whenever the attach socket exists
74 string socket_file
= "/tmp/mono-" + user
+ "/.mono-" + pid
;
76 if (!File
.Exists (socket_file
)) {
77 string trigger_file
= "/tmp/.mono_attach_pid" + pid
;
78 FileStream trigger
= null;
81 trigger
= File
.Create (trigger_file
);
84 // Ask the vm to start the attach mechanism
85 Syscall
.kill ((int)pid
, Signum
.SIGQUIT
);
87 // Wait for the socket file to materialize
89 for (i
= 0; i
< 10; ++i
) {
90 if (File
.Exists (socket_file
))
96 throw new Exception (String
.Format ("Runtime failed to create attach socket '{0}'.", socket_file
));
98 File
.Delete (trigger_file
);
103 * We communicate with the agent inside the runtime using a simlified
104 * version of the .net remoting protocol.
107 string path
= "/tmp/mono-" + user
+ "/.mono-" + pid
;
109 UnixClient client
= new UnixClient (path
);
111 NetworkStream stream
= client
.GetStream ();
114 MemoryStream ms
= new MemoryStream ();
115 BinaryWriter writer
= new BinaryWriter (ms
);
116 write_string (writer
, "attach");
117 write_string (writer
, agent
);
118 write_string (writer
, args
);
121 byte[] magic
= new byte [] { (byte)'M', (byte)'O', (byte)'N', (byte)'O', 1, 0 }
;
122 stream
.Write (magic
, 0, magic
.Length
);
124 // Write payload length
125 new BinaryWriter (stream
).Write ((int)ms
.Length
);
128 stream
.Write (ms
.GetBuffer (), 0, (int)ms
.Length
);
131 enum PrimitiveType
: byte {
133 PRIM_TYPE_STRING
= 18
136 void write_string (BinaryWriter writer
, string s
) {
138 writer
.Write ((sbyte)PrimitiveType
.PRIM_TYPE_NULL
);
140 writer
.Write ((sbyte)PrimitiveType
.PRIM_TYPE_STRING
);
142 writer
.Write ((byte)0);
146 public override string ToString () {
147 return "VirtualMachine (pid=" + pid
+ ")";