Merge pull request #901 from Blewzman/FixAggregateExceptionGetBaseException
[mono.git] / mcs / class / Mono.Debugger.Soft / Mono.Debugger.Soft / VirtualMachine.cs
1 using System;
2 using System.IO;
3 using System.Threading;
4 using System.Net;
5 using System.Diagnostics;
6 using System.Collections;
7 using System.Collections.Generic;
8 using Mono.Cecil.Metadata;
9
10 namespace Mono.Debugger.Soft
11 {
12         public class VirtualMachine : Mirror
13         {
14                 Queue queue;
15                 object queue_monitor;
16                 object startup_monitor;
17                 AppDomainMirror root_domain;
18                 Dictionary<int, EventRequest> requests;
19                 ITargetProcess process;
20
21                 internal Connection conn;
22
23                 VersionInfo version;
24
25                 internal VirtualMachine (ITargetProcess process, Connection conn) : base () {
26                         SetVirtualMachine (this);
27                         queue = new Queue ();
28                         queue_monitor = new Object ();
29                         startup_monitor = new Object ();
30                         requests = new Dictionary <int, EventRequest> ();
31                         this.conn = conn;
32                         this.process = process;
33                         conn.ErrorHandler += ErrorHandler;
34                 }
35
36                 // The standard output of the process is available normally through Process
37                 public StreamReader StandardOutput { get; set; }
38                 public StreamReader StandardError { get; set; }
39
40                 
41                 public Process Process {
42                         get {
43                                 ProcessWrapper pw = process as ProcessWrapper;
44                                 if (pw == null)
45                                     throw new InvalidOperationException ("Process instance not available");
46                                 return pw.Process;
47                         }
48                 }
49
50                 public ITargetProcess TargetProcess {
51                         get {
52                                 return process;
53                         }
54                 }
55
56                 public AppDomainMirror RootDomain {
57                         get {
58                                 return root_domain;
59                         }
60             }
61
62                 public EndPoint EndPoint {
63                         get {
64                                 var tcpConn = conn as TcpConnection;
65                                 if (tcpConn != null)
66                                         return tcpConn.EndPoint;
67                                 return null;
68                         }
69                 }
70
71                 public VersionInfo Version {
72                         get {
73                                 return version;
74                         }
75                 }
76
77                 EventSet current_es;
78                 int current_es_index;
79
80                 /*
81                  * It is impossible to determine when to resume when using this method, since
82                  * the debuggee is suspended only once per event-set, not event.
83                  */
84                 [Obsolete ("Use GetNextEventSet () instead")]
85                 public Event GetNextEvent () {
86                         lock (queue_monitor) {
87                                 if (current_es == null || current_es_index == current_es.Events.Length) {
88                                         if (queue.Count == 0)
89                                                 Monitor.Wait (queue_monitor);
90                                         current_es = (EventSet)queue.Dequeue ();
91                                         current_es_index = 0;
92                                 }
93                                 return current_es.Events [current_es_index ++];
94                         }
95                 }
96
97                 public Event GetNextEvent (int timeout) {
98                         throw new NotImplementedException ();
99                 }
100
101                 public EventSet GetNextEventSet () {
102                         lock (queue_monitor) {
103                                 if (queue.Count == 0)
104                                         Monitor.Wait (queue_monitor);
105
106                                 current_es = null;
107                                 current_es_index = 0;
108
109                                 return (EventSet)queue.Dequeue ();
110                         }
111                 }
112
113                 [Obsolete ("Use GetNextEventSet () instead")]
114                 public T GetNextEvent<T> () where T : Event {
115                         return GetNextEvent () as T;
116                 }
117
118                 public void Suspend () {
119                         conn.VM_Suspend ();
120             }
121
122                 public void Resume () {
123                         try {
124                                 conn.VM_Resume ();
125                         } catch (CommandException ex) {
126                                 if (ex.ErrorCode == ErrorCode.NOT_SUSPENDED)
127                                         throw new VMNotSuspendedException ();
128                                 else
129                                         throw;
130                         }
131             }
132
133                 public void Exit (int exitCode) {
134                         conn.VM_Exit (exitCode);
135                 }
136
137                 public void Detach () {
138                         conn.VM_Dispose ();
139                         conn.Close ();
140                         notify_vm_event (EventType.VMDisconnect, SuspendPolicy.None, 0, 0, null, 0);
141                 }
142
143                 [Obsolete ("This method was poorly named; use the Detach() method instead")]
144                 public void Dispose ()
145                 {
146                         Detach ();
147                 }
148
149                 public void ForceDisconnect ()
150                 {
151                         conn.ForceDisconnect ();
152                 }
153
154                 public IList<ThreadMirror> GetThreads () {
155                         long[] ids = vm.conn.VM_GetThreads ();
156                         ThreadMirror[] res = new ThreadMirror [ids.Length];
157                         for (int i = 0; i < ids.Length; ++i)
158                                 res [i] = GetThread (ids [i]);
159                         return res;
160                 }
161
162                 // Same as the mirrorOf methods in JDI
163                 public PrimitiveValue CreateValue (object value) {
164                         if (value == null)
165                                 return new PrimitiveValue (vm, null);
166
167                         if (!value.GetType ().IsPrimitive)
168                                 throw new ArgumentException ("value must be of a primitive type instead of '" + value.GetType () + "'", "value");
169
170                         return new PrimitiveValue (vm, value);
171                 }
172
173                 public EnumMirror CreateEnumMirror (TypeMirror type, PrimitiveValue value) {
174                         return new EnumMirror (this, type, value);
175                 }
176
177                 //
178                 // Enable send and receive timeouts on the connection and send a keepalive event
179                 // every 'keepalive_interval' milliseconds.
180                 //
181
182                 public void SetSocketTimeouts (int send_timeout, int receive_timeout, int keepalive_interval)
183                 {
184                         conn.SetSocketTimeouts (send_timeout, receive_timeout, keepalive_interval);
185                 }
186
187                 //
188                 // Methods to create event request objects
189                 //
190                 public BreakpointEventRequest CreateBreakpointRequest (MethodMirror method, long il_offset) {
191                         return new BreakpointEventRequest (this, method, il_offset);
192                 }
193
194                 public BreakpointEventRequest CreateBreakpointRequest (Location loc) {
195                         if (loc == null)
196                                 throw new ArgumentNullException ("loc");
197                         CheckMirror (loc);
198                         return new BreakpointEventRequest (this, loc.Method, loc.ILOffset);
199                 }
200
201                 public StepEventRequest CreateStepRequest (ThreadMirror thread) {
202                         return new StepEventRequest (this, thread);
203                 }
204
205                 public MethodEntryEventRequest CreateMethodEntryRequest () {
206                         return new MethodEntryEventRequest (this);
207                 }
208
209                 public MethodExitEventRequest CreateMethodExitRequest () {
210                         return new MethodExitEventRequest (this);
211                 }
212
213                 public ExceptionEventRequest CreateExceptionRequest (TypeMirror exc_type) {
214                         return new ExceptionEventRequest (this, exc_type, true, true);
215                 }
216
217                 public ExceptionEventRequest CreateExceptionRequest (TypeMirror exc_type, bool caught, bool uncaught) {
218                         return new ExceptionEventRequest (this, exc_type, caught, uncaught);
219                 }
220
221                 public AssemblyLoadEventRequest CreateAssemblyLoadRequest () {
222                         return new AssemblyLoadEventRequest (this);
223                 }
224
225                 public TypeLoadEventRequest CreateTypeLoadRequest () {
226                         return new TypeLoadEventRequest (this);
227                 }
228
229                 public void EnableEvents (params EventType[] events) {
230                         EnableEvents (events, SuspendPolicy.All);
231                 }
232
233                 public void EnableEvents (EventType[] events, SuspendPolicy suspendPolicy) {
234                         foreach (EventType etype in events) {
235                                 if (etype == EventType.Breakpoint)
236                                         throw new ArgumentException ("Breakpoint events cannot be requested using EnableEvents", "events");
237                                 conn.EnableEvent (etype, suspendPolicy, null);
238                         }
239                 }
240
241                 public BreakpointEventRequest SetBreakpoint (MethodMirror method, long il_offset) {
242                         BreakpointEventRequest req = CreateBreakpointRequest (method, il_offset);
243
244                         req.Enable ();
245
246                         return req;
247                 }
248
249                 public void ClearAllBreakpoints () {
250                         conn.ClearAllBreakpoints ();
251                 }
252                 
253                 public void Disconnect () {
254                         conn.Close ();
255                 }
256
257                 //
258                 // Return a list of TypeMirror objects for all loaded types which reference the
259                 // source file FNAME. Might return false positives.
260                 // Since protocol version 2.7.
261                 //
262                 public IList<TypeMirror> GetTypesForSourceFile (string fname, bool ignoreCase) {
263                         long[] ids = conn.VM_GetTypesForSourceFile (fname, ignoreCase);
264                         var res = new TypeMirror [ids.Length];
265                         for (int i = 0; i < ids.Length; ++i)
266                                 res [i] = GetType (ids [i]);
267                         return res;
268                 }
269
270                 //
271                 // Return a list of TypeMirror objects for all loaded types named 'NAME'.
272                 // NAME should be in the the same for as with Assembly.GetType ().
273                 // Since protocol version 2.9.
274                 //
275                 public IList<TypeMirror> GetTypes (string name, bool ignoreCase) {
276                         long[] ids = conn.VM_GetTypes (name, ignoreCase);
277                         var res = new TypeMirror [ids.Length];
278                         for (int i = 0; i < ids.Length; ++i)
279                                 res [i] = GetType (ids [i]);
280                         return res;
281                 }
282                 
283                 internal void queue_event_set (EventSet es) {
284                         lock (queue_monitor) {
285                                 queue.Enqueue (es);
286                                 Monitor.Pulse (queue_monitor);
287                         }
288                 }
289
290                 internal void ErrorHandler (object sender, ErrorHandlerEventArgs args) {
291                         switch (args.ErrorCode) {
292                         case ErrorCode.INVALID_OBJECT:
293                                 throw new ObjectCollectedException ();
294                         case ErrorCode.INVALID_FRAMEID:
295                                 throw new InvalidStackFrameException ();
296                         case ErrorCode.NOT_SUSPENDED:
297                                 throw new VMNotSuspendedException ();
298                         case ErrorCode.NOT_IMPLEMENTED:
299                                 throw new NotSupportedException ("This request is not supported by the protocol version implemented by the debuggee.");
300                         case ErrorCode.ABSENT_INFORMATION:
301                                 throw new AbsentInformationException ();
302                         case ErrorCode.NO_SEQ_POINT_AT_IL_OFFSET:
303                                 throw new ArgumentException ("Cannot set breakpoint on the specified IL offset.");
304                         default:
305                                 throw new CommandException (args.ErrorCode);
306                         }
307                 }
308
309                 /* Wait for the debuggee to start up and connect to it */
310                 internal void connect () {
311                         conn.Connect ();
312
313                         // Test the connection
314                         version = conn.Version;
315                         if (version.MajorVersion != Connection.MAJOR_VERSION)
316                                 throw new NotSupportedException (String.Format ("The debuggee implements protocol version {0}.{1}, while {2}.{3} is required.", version.MajorVersion, version.MinorVersion, Connection.MAJOR_VERSION, Connection.MINOR_VERSION));
317
318                         long root_domain_id = conn.RootDomain;
319                         root_domain = GetDomain (root_domain_id);
320                 }
321
322                 internal void notify_vm_event (EventType evtype, SuspendPolicy spolicy, int req_id, long thread_id, string vm_uri, int exit_code) {
323                         //Console.WriteLine ("Event: " + evtype + "(" + vm_uri + ")");
324
325                         switch (evtype) {
326                         case EventType.VMStart:
327                                 /* Notify the main thread that the debuggee started up */
328                                 lock (startup_monitor) {
329                                         Monitor.Pulse (startup_monitor);
330                                 }
331                                 queue_event_set (new EventSet (this, spolicy, new Event[] { new VMStartEvent (vm, req_id, thread_id) }));
332                                 break;
333                         case EventType.VMDeath:
334                                 queue_event_set (new EventSet (this, spolicy, new Event[] { new VMDeathEvent (vm, req_id, exit_code) }));
335                                 break;
336                         case EventType.VMDisconnect:
337                                 queue_event_set (new EventSet (this, spolicy, new Event[] { new VMDisconnectEvent (vm, req_id) }));
338                                 break;
339                         default:
340                                 throw new Exception ();
341                         }
342                 }
343
344                 //
345                 // Methods to create instances of mirror objects
346                 //
347
348                 /*
349                 class MirrorCache<T> {
350                         static Dictionary <long, T> mirrors;
351                         static object mirror_lock = new object ();
352
353                         internal static T GetMirror (VirtualMachine vm, long id) {
354                                 lock (mirror_lock) {
355                                 if (mirrors == null)
356                                         mirrors = new Dictionary <long, T> ();
357                                 T obj;
358                                 if (!mirrors.TryGetValue (id, out obj)) {
359                                         obj = CreateMirror (vm, id);
360                                         mirrors [id] = obj;
361                                 }
362                                 return obj;
363                                 }
364                         }
365
366                         internal static T CreateMirror (VirtualMachine vm, long id) {
367                         }
368                 }
369                 */
370
371                 // FIXME: When to remove items from the cache ?
372
373                 Dictionary <long, MethodMirror> methods;
374                 object methods_lock = new object ();
375
376                 internal MethodMirror GetMethod (long id) {
377                         lock (methods_lock) {
378                                 if (methods == null)
379                                         methods = new Dictionary <long, MethodMirror> ();
380                                 MethodMirror obj;
381                                 if (id == 0)
382                                         return null;
383                                 if (!methods.TryGetValue (id, out obj)) {
384                                         obj = new MethodMirror (this, id);
385                                         methods [id] = obj;
386                                 }
387                                 return obj;
388                         }
389             }
390
391                 Dictionary <long, AssemblyMirror> assemblies;
392                 object assemblies_lock = new object ();
393
394                 internal AssemblyMirror GetAssembly (long id) {
395                         lock (assemblies_lock) {
396                                 if (assemblies == null)
397                                         assemblies = new Dictionary <long, AssemblyMirror> ();
398                                 AssemblyMirror obj;
399                                 if (id == 0)
400                                         return null;
401                                 if (!assemblies.TryGetValue (id, out obj)) {
402                                         obj = new AssemblyMirror (this, id);
403                                         assemblies [id] = obj;
404                                 }
405                                 return obj;
406                         }
407             }
408
409                 Dictionary <long, ModuleMirror> modules;
410                 object modules_lock = new object ();
411
412                 internal ModuleMirror GetModule (long id) {
413                         lock (modules_lock) {
414                                 if (modules == null)
415                                         modules = new Dictionary <long, ModuleMirror> ();
416                                 ModuleMirror obj;
417                                 if (id == 0)
418                                         return null;
419                                 if (!modules.TryGetValue (id, out obj)) {
420                                         obj = new ModuleMirror (this, id);
421                                         modules [id] = obj;
422                                 }
423                                 return obj;
424                         }
425             }
426
427                 Dictionary <long, AppDomainMirror> domains;
428                 object domains_lock = new object ();
429
430                 internal AppDomainMirror GetDomain (long id) {
431                         lock (domains_lock) {
432                                 if (domains == null)
433                                         domains = new Dictionary <long, AppDomainMirror> ();
434                                 AppDomainMirror obj;
435                                 if (id == 0)
436                                         return null;
437                                 if (!domains.TryGetValue (id, out obj)) {
438                                         obj = new AppDomainMirror (this, id);
439                                         domains [id] = obj;
440                                 }
441                                 return obj;
442                         }
443             }
444
445                 Dictionary <long, TypeMirror> types;
446                 object types_lock = new object ();
447
448                 internal TypeMirror GetType (long id) {
449                         lock (types_lock) {
450                                 if (types == null)
451                                         types = new Dictionary <long, TypeMirror> ();
452                                 TypeMirror obj;
453                                 if (id == 0)
454                                         return null;
455                                 if (!types.TryGetValue (id, out obj)) {
456                                         obj = new TypeMirror (this, id);
457                                         types [id] = obj;
458                                 }
459                                 return obj;
460                         }
461             }
462
463                 internal TypeMirror[] GetTypes (long[] ids) {
464                         var res = new TypeMirror [ids.Length];
465                         for (int i = 0; i < ids.Length; ++i)
466                                 res [i] = GetType (ids [i]);
467                         return res;
468                 }
469
470                 Dictionary <long, ObjectMirror> objects;
471                 object objects_lock = new object ();
472
473                 internal T GetObject<T> (long id, long domain_id, long type_id) where T : ObjectMirror {
474                         lock (objects_lock) {
475                                 if (objects == null)
476                                         objects = new Dictionary <long, ObjectMirror> ();
477                                 ObjectMirror obj;
478                                 if (!objects.TryGetValue (id, out obj)) {
479                                         /*
480                                          * Obtain the domain/type of the object to determine the type of
481                                          * object we need to create.
482                                          */
483                                         if (domain_id == 0 || type_id == 0) {
484                                                 if (conn.Version.AtLeast (2, 5)) {
485                                                         var info = conn.Object_GetInfo (id);
486                                                         domain_id = info.domain_id;
487                                                         type_id = info.type_id;
488                                                 } else {
489                                                         if (domain_id == 0)
490                                                                 domain_id = conn.Object_GetDomain (id);
491                                                         if (type_id == 0)
492                                                                 type_id = conn.Object_GetType (id);
493                                                 }
494                                         }
495                                         AppDomainMirror d = GetDomain (domain_id);
496                                         TypeMirror t = GetType (type_id);
497
498                                         if (t.Assembly == d.Corlib && t.Namespace == "System.Threading" && t.Name == "Thread")
499                                                 obj = new ThreadMirror (this, id, t, d);
500                                         else if (t.Assembly == d.Corlib && t.Namespace == "System" && t.Name == "String")
501                                                 obj = new StringMirror (this, id, t, d);
502                                         else if (typeof (T) == typeof (ArrayMirror))
503                                                 obj = new ArrayMirror (this, id, t, d);
504                                         else
505                                                 obj = new ObjectMirror (this, id, t, d);
506                                         objects [id] = obj;
507                                 }
508                                 return (T)obj;
509                         }
510             }
511
512                 internal T GetObject<T> (long id) where T : ObjectMirror {
513                         return GetObject<T> (id, 0, 0);
514                 }
515
516                 internal ObjectMirror GetObject (long objid) {
517                         return GetObject<ObjectMirror> (objid);
518                 }
519
520                 internal ThreadMirror GetThread (long id) {
521                         return GetObject <ThreadMirror> (id);
522                 }
523
524                 object requests_lock = new object ();
525
526                 internal void AddRequest (EventRequest req, int id) {
527                         lock (requests_lock) {
528                                 requests [id] = req;
529                         }
530                 }
531
532                 internal void RemoveRequest (EventRequest req, int id) {
533                         lock (requests_lock) {
534                                 requests.Remove (id);
535                         }
536                 }
537
538                 internal EventRequest GetRequest (int id) {
539                         lock (requests_lock) {
540                                 return requests [id];
541                         }
542                 }
543
544                 internal Value DecodeValue (ValueImpl v) {
545                         if (v.Value != null)
546                                 return new PrimitiveValue (this, v.Value);
547
548                         switch (v.Type) {
549                         case ElementType.Void:
550                                 return null;
551                         case ElementType.SzArray:
552                         case ElementType.Array:
553                                 return GetObject<ArrayMirror> (v.Objid);
554                         case ElementType.String:
555                                 return GetObject<StringMirror> (v.Objid);
556                         case ElementType.Class:
557                         case ElementType.Object:
558                                 return GetObject (v.Objid);
559                         case ElementType.ValueType:
560                                 if (v.IsEnum)
561                                         return new EnumMirror (this, GetType (v.Klass), DecodeValues (v.Fields));
562                                 else
563                                         return new StructMirror (this, GetType (v.Klass), DecodeValues (v.Fields));
564                         case (ElementType)ValueTypeId.VALUE_TYPE_ID_NULL:
565                                 return new PrimitiveValue (this, null);
566                         default:
567                                 throw new NotImplementedException ("" + v.Type);
568                         }
569                 }
570
571                 internal Value[] DecodeValues (ValueImpl[] values) {
572                         Value[] res = new Value [values.Length];
573                         for (int i = 0; i < values.Length; ++i)
574                                 res [i] = DecodeValue (values [i]);
575                         return res;
576                 }
577
578                 internal ValueImpl EncodeValue (Value v) {
579                         if (v is PrimitiveValue) {
580                                 object val = (v as PrimitiveValue).Value;
581                                 if (val == null)
582                                         return new ValueImpl { Type = (ElementType)ValueTypeId.VALUE_TYPE_ID_NULL, Objid = 0 };
583                                 else
584                                         return new ValueImpl { Value = val };
585                         } else if (v is ObjectMirror) {
586                                 return new ValueImpl { Type = ElementType.Object, Objid = (v as ObjectMirror).Id };
587                         } else if (v is StructMirror) {
588                                 return new ValueImpl { Type = ElementType.ValueType, Klass = (v as StructMirror).Type.Id, Fields = EncodeValues ((v as StructMirror).Fields) };
589                         } else {
590                                 throw new NotSupportedException ();
591                         }
592                 }
593
594                 internal ValueImpl[] EncodeValues (IList<Value> values) {
595                         ValueImpl[] res = new ValueImpl [values.Count];
596                         for (int i = 0; i < values.Count; ++i)
597                                 res [i] = EncodeValue (values [i]);
598                         return res;
599                 }
600
601                 internal void CheckProtocolVersion (int major, int minor) {
602                         if (!conn.Version.AtLeast (major, minor))
603                                 throw new NotSupportedException ("This request is not supported by the protocol version implemented by the debuggee.");
604                 }
605     }
606
607         class EventHandler : MarshalByRefObject, IEventHandler
608         {               
609                 VirtualMachine vm;
610
611                 public EventHandler (VirtualMachine vm) {
612                         this.vm = vm;
613                 }
614
615                 public void Events (SuspendPolicy suspend_policy, EventInfo[] events) {
616                         var l = new List<Event> ();
617
618                         for (int i = 0; i < events.Length; ++i) {
619                                 EventInfo ei = events [i];
620                                 int req_id = ei.ReqId;
621                                 long thread_id = ei.ThreadId;
622                                 long id = ei.Id;
623                                 long loc = ei.Location;
624
625                                 switch (ei.EventType) {
626                                 case EventType.VMStart:
627                                         vm.notify_vm_event (EventType.VMStart, suspend_policy, req_id, thread_id, null, 0);
628                                         break;
629                                 case EventType.VMDeath:
630                                         vm.notify_vm_event (EventType.VMDeath, suspend_policy, req_id, thread_id, null, ei.ExitCode);
631                                         break;
632                                 case EventType.ThreadStart:
633                                         l.Add (new ThreadStartEvent (vm, req_id, id));
634                                         break;
635                                 case EventType.ThreadDeath:
636                                         l.Add (new ThreadDeathEvent (vm, req_id, id));
637                                         break;
638                                 case EventType.AssemblyLoad:
639                                         l.Add (new AssemblyLoadEvent (vm, req_id, thread_id, id));
640                                         break;
641                                 case EventType.AssemblyUnload:
642                                         l.Add (new AssemblyUnloadEvent (vm, req_id, thread_id, id));
643                                         break;
644                                 case EventType.TypeLoad:
645                                         l.Add (new TypeLoadEvent (vm, req_id, thread_id, id));
646                                         break;
647                                 case EventType.MethodEntry:
648                                         l.Add (new MethodEntryEvent (vm, req_id, thread_id, id));
649                                         break;
650                                 case EventType.MethodExit:
651                                         l.Add (new MethodExitEvent (vm, req_id, thread_id, id));
652                                         break;
653                                 case EventType.Breakpoint:
654                                         l.Add (new BreakpointEvent (vm, req_id, thread_id, id, loc));
655                                         break;
656                                 case EventType.Step:
657                                         l.Add (new StepEvent (vm, req_id, thread_id, id, loc));
658                                         break;
659                                 case EventType.Exception:
660                                         l.Add (new ExceptionEvent (vm, req_id, thread_id, id, loc));
661                                         break;
662                                 case EventType.AppDomainCreate:
663                                         l.Add (new AppDomainCreateEvent (vm, req_id, thread_id, id));
664                                         break;
665                                 case EventType.AppDomainUnload:
666                                         l.Add (new AppDomainUnloadEvent (vm, req_id, thread_id, id));
667                                         break;
668                                 case EventType.UserBreak:
669                                         l.Add (new UserBreakEvent (vm, req_id, thread_id));
670                                         break;
671                                 case EventType.UserLog:
672                                         l.Add (new UserLogEvent (vm, req_id, thread_id, ei.Level, ei.Category, ei.Message));
673                                         break;
674                                 default:
675                                         break;
676                                 }
677                         }
678                         
679                         if (l.Count > 0)
680                                 vm.queue_event_set (new EventSet (vm, suspend_policy, l.ToArray ()));
681                 }
682
683                 public void VMDisconnect (int req_id, long thread_id, string vm_uri) {
684                         vm.notify_vm_event (EventType.VMDisconnect, SuspendPolicy.None, req_id, thread_id, vm_uri, 0);
685         }
686     }
687
688         public class CommandException : Exception {
689
690                 internal CommandException (ErrorCode error_code) : base ("Debuggee returned error code " + error_code + ".") {
691                         ErrorCode = error_code;
692                 }
693
694                 public ErrorCode ErrorCode {
695                         get; set;
696                 }
697         }
698
699         public class VMNotSuspendedException : InvalidOperationException
700         {
701                 public VMNotSuspendedException () : base ("The vm is not suspended.")
702                 {
703                 }
704         }
705 }