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 () {
48 StringBuilder sb = new StringBuilder (len);
50 int res = Syscall.readlink ("/proc/" + pid + "/cwd", sb);
52 throw new IOException ("Syscall.readlink () failed with error " + res + ".");
53 else if (res == len) {
56 return sb.ToString ();
62 * Return the list of running mono vms owned by the current user. The
63 * result includes the current vm too.
65 public static List<VirtualMachine> GetVirtualMachines () {
66 PerformanceCounterCategory p = new PerformanceCounterCategory (".NET CLR JIT");
67 string[] machines = p.GetInstanceNames ();
69 var res = new List<VirtualMachine> ();
71 foreach (string s in machines) {
72 // The names are in the form 'pid/name'
73 int pos = s.IndexOf ('/');
75 res.Add (new VirtualMachine (Int32.Parse (s.Substring (0, pos))));
81 * Loads the specific agent assembly into this vm.
83 public void Attach (string agent, string args) {
84 string user = UnixUserInfo.GetRealUser ().UserName;
86 // Check whenever the attach socket exists
87 string socket_file = "/tmp/mono-" + user + "/.mono-" + pid;
89 if (!File.Exists (socket_file)) {
90 string trigger_file = "/tmp/.mono_attach_pid" + pid;
91 FileStream trigger = null;
94 trigger = File.Create (trigger_file);
97 // Ask the vm to start the attach mechanism
98 Syscall.kill ((int)pid, Signum.SIGQUIT);
100 // Wait for the socket file to materialize
102 for (i = 0; i < 10; ++i) {
103 if (File.Exists (socket_file))
109 throw new Exception (String.Format ("Runtime failed to create attach socket '{0}'.", socket_file));
111 File.Delete (trigger_file);
116 * We communicate with the agent inside the runtime using a simlified
117 * version of the .net remoting protocol.
120 string path = "/tmp/mono-" + user + "/.mono-" + pid;
122 UnixClient client = new UnixClient (path);
124 NetworkStream stream = client.GetStream ();
127 MemoryStream ms = new MemoryStream ();
128 BinaryWriter writer = new BinaryWriter (ms);
129 write_string (writer, "attach");
130 write_string (writer, agent);
131 write_string (writer, args);
134 byte[] magic = new byte [] { (byte)'M', (byte)'O', (byte)'N', (byte)'O', 1, 0 };
135 stream.Write (magic, 0, magic.Length);
137 // Write payload length
138 new BinaryWriter (stream).Write ((int)ms.Length);
141 stream.Write (ms.GetBuffer (), 0, (int)ms.Length);
144 enum PrimitiveType : byte {
146 PRIM_TYPE_STRING = 18
149 void write_string (BinaryWriter writer, string s) {
151 writer.Write ((sbyte)PrimitiveType.PRIM_TYPE_NULL);
153 writer.Write ((sbyte)PrimitiveType.PRIM_TYPE_STRING);
158 public override string ToString () {
159 return "VirtualMachine (pid=" + pid + ")";