2 using System
.Collections
.Generic
;
3 using System
.Runtime
.InteropServices
;
4 using System
.Runtime
.Remoting
.Lifetime
;
6 using ST
= System
.Threading
;
10 using MD
= Mono
.Debugger
;
11 using ML
= Mono
.Debugger
.Languages
;
12 using DL
= Mono
.Debugging
.Client
;
13 using DB
= Mono
.Debugging
.Backend
;
15 using Mono
.Debugging
.Client
;
16 using Mono
.Debugging
.Backend
.Mdb
;
18 namespace DebuggerServer
20 class DebuggerServer
: MarshalByRefObject
, IDebuggerServer
, ISponsor
22 IDebuggerController controller
;
24 MD
.DebuggerSession session
;
26 MD
.GUIManager guiManager
;
28 bool internalInterruptionRequested
;
29 List
<ST
.WaitCallback
> stoppedWorkQueue
= new List
<ST
.WaitCallback
> ();
30 List
<ST
.WaitCallback
> eventQueue
= new List
<ST
.WaitCallback
> ();
33 ExpressionEvaluator evaluator
= new NRefactoryEvaluator ();
34 MD
.Thread activeThread
;
35 Dictionary
<int,BreakEvent
> events
= new Dictionary
<int,BreakEvent
> ();
36 Dictionary
<int,string> lastConditionValue
= new Dictionary
<int,string> ();
38 DateTime lastBreakEventUpdate
= DateTime
.Now
;
39 Dictionary
<int, ST
.WaitCallback
> breakUpdates
= new Dictionary
<int,ST
.WaitCallback
> ();
40 bool breakUpdateEventsQueued
;
42 AsyncEvaluationTracker asyncEvaluationTracker
;
43 RuntimeInvokeManager invokeManager
;
45 public const int DefaultAsyncSwitchTimeout
= 60;
46 public const int DefaultEvaluationTimeout
= 1000;
47 public const int DefaultChildEvaluationTimeout
= 5000;
49 const int BreakEventUpdateNotifyDelay
= 500;
51 public DebuggerServer (IDebuggerController dc
)
54 MarshalByRefObject mbr
= (MarshalByRefObject
)controller
;
55 ILease lease
= mbr
.GetLifetimeService() as ILease
;
59 ST
.Thread t
= new ST
.Thread ((ST
.ThreadStart
)EventDispatcher
);
60 t
.IsBackground
= true;
63 invokeManager
= new RuntimeInvokeManager ();
64 asyncEvaluationTracker
= new AsyncEvaluationTracker ();
67 public override object InitializeLifetimeService ()
72 public ExpressionEvaluator Evaluator
{
73 get { return evaluator; }
76 public AsyncEvaluationTracker AsyncEvaluationTracker
{
78 return asyncEvaluationTracker
;
82 #region IDebugger Members
84 public void Run (DL
.DebuggerStartInfo startInfo
)
87 if (startInfo
== null)
88 throw new ArgumentNullException ("startInfo");
92 DebuggerConfiguration config
= new DebuggerConfiguration ();
93 config
.LoadConfiguration ();
94 debugger
= new MD
.Debugger (config
);
96 debugger
.ModuleLoadedEvent
+= OnModuleLoadedEvent
;
97 debugger
.ModuleUnLoadedEvent
+= OnModuleUnLoadedEvent
;
99 debugger
.ProcessReachedMainEvent
+= delegate (MD
.Debugger deb
, MD
.Process proc
) {
100 OnInitialized (deb
, proc
);
104 DebuggerOptions options
= DebuggerOptions
.ParseCommandLine (new string[] { startInfo.Command }
);
105 options
.WorkingDirectory
= startInfo
.WorkingDirectory
;
106 Environment
.CurrentDirectory
= startInfo
.WorkingDirectory
;
107 options
.StopInMain
= false;
109 if (!string.IsNullOrEmpty (startInfo
.Arguments
))
110 options
.InferiorArgs
= startInfo
.Arguments
.Split(' ');
112 if (startInfo
.EnvironmentVariables
!= null) {
113 foreach (KeyValuePair
<string,string> env
in startInfo
.EnvironmentVariables
)
114 options
.SetEnvironment (env
.Key
, env
.Value
);
116 session
= new MD
.DebuggerSession (config
, options
, "main", null);
118 debugger
.Run(session
);
120 } catch (Exception e
) {
121 Console
.WriteLine ("error: " + e
.ToString ());
126 public void AttachToProcess (int pid
)
128 Report
.Initialize ();
130 DebuggerConfiguration config
= new DebuggerConfiguration ();
131 config
.LoadConfiguration ();
132 debugger
= new MD
.Debugger (config
);
134 DebuggerOptions options
= DebuggerOptions
.ParseCommandLine (new string[0]);
135 options
.StopInMain
= false;
136 session
= new MD
.DebuggerSession (config
, options
, "main", (IExpressionParser
) null);
138 Process proc
= debugger
.Attach (session
, pid
);
139 OnInitialized (debugger
, proc
);
141 ST
.ThreadPool
.QueueUserWorkItem (delegate {
146 public void Detach ()
148 CancelRuntimeInvokes ();
149 RunWhenStopped (delegate {
152 } catch (Exception ex
) {
153 Console
.WriteLine (ex
);
162 CancelRuntimeInvokes ();
163 QueueTask (delegate {
164 if (internalInterruptionRequested
) {
165 // Stop already internally requested. By resetting the flag, the interruption
166 // won't be considered internal anymore and the session won't be automatically restarted.
167 internalInterruptionRequested
= false;
170 guiManager
.Stop (process
.MainThread
);
176 CancelRuntimeInvokes ();
183 public void NextLine ()
186 throw new InvalidOperationException ("Target already running");
188 guiManager
.StepOver (activeThread
);
191 public void StepLine ()
194 throw new InvalidOperationException ("Target already running");
196 guiManager
.StepInto (activeThread
);
199 public void StepInstruction ()
202 throw new InvalidOperationException ("Target already running");
204 activeThread
.StepInstruction ();
207 public void NextInstruction ()
210 throw new InvalidOperationException ("Target already running");
212 activeThread
.NextInstruction ();
215 public void Finish ()
218 throw new InvalidOperationException ("Target already running");
220 guiManager
.StepOut (activeThread
);
223 public void Continue ()
226 throw new InvalidOperationException ("Target already running");
228 QueueTask (delegate {
229 guiManager
.Continue (activeThread
);
233 public int InsertBreakEvent (DL
.BreakEvent be
, bool enable
)
235 CancelRuntimeInvokes ();
236 DL
.Breakpoint bp
= be
as DL
.Breakpoint
;
240 MD
.SourceLocation location
= new MD
.SourceLocation (bp
.FileName
, bp
.Line
);
241 ev
= session
.InsertBreakpoint (ThreadGroup
.Global
, location
);
243 else if (be
is Catchpoint
) {
244 Catchpoint cp
= (Catchpoint
) be
;
245 ML
.TargetType exc
= null;
246 foreach (Module mod
in process
.Modules
) {
247 exc
= mod
.Language
.LookupType (cp
.ExceptionName
);
252 throw new Exception ("Unknown exception type.");
253 ev
= session
.InsertExceptionCatchPoint (process
.MainThread
, ThreadGroup
.Global
, exc
);
256 ev
.IsEnabled
= enable
;
259 RunWhenStopped (delegate {
261 ev
.Activate (process
.MainThread
);
262 } catch (Exception ex
) {
263 Console
.WriteLine (ex
);
268 if (bp
!= null && !running
&& activeThread
.CurrentFrame
!= null && !string.IsNullOrEmpty (bp
.ConditionExpression
) && bp
.BreakIfConditionChanges
) {
269 // Initial expression evaluation
270 EvaluationContext ctx
= new EvaluationContext (activeThread
, activeThread
.CurrentFrame
, -1);
271 ML
.TargetObject ob
= EvaluateExp (ctx
, bp
.ConditionExpression
);
273 lastConditionValue
[ev
.Index
] = evaluator
.TargetObjectToExpression (ctx
, ob
);
276 events
[ev
.Index
] = be
;
280 public void RemoveBreakEvent (int handle
)
282 CancelRuntimeInvokes ();
283 RunWhenStopped (delegate {
285 Event ev
= session
.GetEvent (handle
);
286 session
.DeleteEvent (ev
);
287 events
.Remove (handle
);
288 } catch (Exception ex
) {
289 Console
.WriteLine (ex
);
294 public void EnableBreakEvent (int handle
, bool enable
)
296 CancelRuntimeInvokes ();
297 RunWhenStopped (delegate {
298 Event ev
= session
.GetEvent (handle
);
300 ev
.Activate (process
.MainThread
);
302 ev
.Deactivate (process
.MainThread
);
306 public object UpdateBreakEvent (object handle
, DL
.BreakEvent bp
)
308 events
[(int)handle
] = bp
;
312 bool BreakEventCheck (MD
.TargetEventArgs args
)
314 MD
.StackFrame frame
= args
.Frame
;
315 if (!(args
.Data
is int))
318 int eventHandle
= (int) args
.Data
;
321 if (!events
.TryGetValue (eventHandle
, out be
))
325 if (be
.HitCount
> 0) {
327 DispatchEvent (delegate {
328 NotifyBreakEventUpdate (eventHandle
, be
.HitCount
, null);
333 EvaluationContext ctx
= new EvaluationContext (frame
.Thread
, frame
, -1);
334 DL
.Breakpoint bp
= be
as DL
.Breakpoint
;
335 if (bp
!= null && !string.IsNullOrEmpty (bp
.ConditionExpression
)) {
336 ML
.TargetObject val
= EvaluateExp (ctx
, bp
.ConditionExpression
);
339 if (bp
.BreakIfConditionChanges
) {
340 string current
= evaluator
.TargetObjectToExpression (ctx
, val
);
342 bool found
= lastConditionValue
.TryGetValue (eventHandle
, out last
);
343 lastConditionValue
[eventHandle
] = current
;
344 if (!found
|| last
== current
)
347 ML
.TargetFundamentalObject fob
= val
as ML
.TargetFundamentalObject
;
350 object ob
= fob
.GetObject (frame
.Thread
);
351 if (!(ob
is bool) || !(bool)ob
)
356 switch (be
.HitAction
) {
357 case HitAction
.Break
:
359 case HitAction
.CustomAction
:
360 return controller
.OnCustomBreakpointAction (be
.CustomActionId
, eventHandle
);
361 case HitAction
.PrintExpression
:
362 if (string.IsNullOrEmpty (be
.TraceExpression
) || frame
== null)
364 ML
.TargetObject val
= EvaluateExp (ctx
, be
.TraceExpression
);
366 string str
= evaluator
.TargetObjectToString (ctx
, val
);
367 DispatchEvent (delegate {
368 controller
.OnTargetOutput (false, str
+ "\n");
369 NotifyBreakEventUpdate (eventHandle
, -1, str
);
377 ML
.TargetObject
EvaluateExp (EvaluationContext ctx
, string exp
)
381 EvaluationOptions ops
= new EvaluationOptions ();
382 ops
.CanEvaluateMethods
= true;
383 var = (ValueReference
) Server
.Instance
.Evaluator
.Evaluate (ctx
, exp
, ops
);
390 void NotifyBreakEventUpdate (int eventHandle
, int hitCount
, string lastTrace
)
396 int span
= (int) (DateTime
.Now
- lastBreakEventUpdate
).TotalMilliseconds
;
397 if (span
>= BreakEventUpdateNotifyDelay
&& !breakUpdateEventsQueued
) {
398 // Last update was more than 0.5s ago. The update can be sent.
399 lastBreakEventUpdate
= DateTime
.Now
;
402 // Queue the event notifications to avoid wasting too much time
403 breakUpdates
[eventHandle
] = delegate {
404 controller
.UpdateBreakpoint (eventHandle
, hitCount
, lastTrace
);
406 if (!breakUpdateEventsQueued
) {
407 breakUpdateEventsQueued
= true;
409 ST
.ThreadPool
.QueueUserWorkItem (delegate {
410 ST
.Thread
.Sleep (BreakEventUpdateNotifyDelay
- span
);
411 List
<ST
.WaitCallback
> copy
;
412 lock (breakUpdates
) {
413 copy
= new List
<ST
.WaitCallback
> (breakUpdates
.Values
);
414 breakUpdates
.Clear ();
415 breakUpdateEventsQueued
= false;
416 lastBreakEventUpdate
= DateTime
.Now
;
418 foreach (ST
.WaitCallback wc
in copy
)
425 controller
.UpdateBreakpoint (eventHandle
, hitCount
, lastTrace
);
428 public ThreadInfo
[] GetThreads (int processId
)
430 MD
.Process p
= GetProcess (processId
);
432 return new ThreadInfo
[0];
433 List
<DL
.ThreadInfo
> list
= new List
<DL
.ThreadInfo
> ();
434 foreach (MD
.Thread t
in p
.GetThreads ()) {
435 DL
.ThreadInfo ct
= CreateThreadInfo (t
);
438 return list
.ToArray ();
441 public ProcessInfo
[] GetPocesses ()
443 List
<DL
.ProcessInfo
> list
= new List
<DL
.ProcessInfo
> ();
444 foreach (MD
.Process p
in debugger
.Processes
)
445 list
.Add (new DL
.ProcessInfo (p
.ID
, p
.TargetApplication
+ " " + string.Join (" ", p
.CommandLineArguments
)));
446 return list
.ToArray ();
449 ThreadInfo
CreateThreadInfo (MD
.Thread t
)
452 if (t
.CurrentFrame
!= null && t
.CurrentFrame
.SourceLocation
!= null) {
453 loc
= t
.CurrentFrame
.ToString ();
457 return new ThreadInfo (t
.Process
.ID
, t
.ID
, t
.Name
, loc
);
460 public DL
.Backtrace
GetThreadBacktrace (int processId
, int threadId
)
462 MD
.Thread t
= GetThread (processId
, threadId
);
463 if (t
!= null && t
.IsStopped
)
464 return CreateBacktrace (t
);
469 public void SetActiveThread (int processId
, int threadId
)
471 activeThread
= GetThread (processId
, threadId
);
474 MD
.Thread
GetThread (int procId
, int threadId
)
476 MD
.Process proc
= GetProcess (procId
);
478 foreach (MD
.Thread t
in proc
.GetThreads ()) {
479 if (t
.ID
== threadId
)
486 MD
.Process
GetProcess (int id
)
488 foreach (MD
.Process p
in debugger
.Processes
) {
495 public AssemblyLine
[] DisassembleFile (string file
)
497 CancelRuntimeInvokes ();
502 /* SourceFile sourceFile = session.FindFile (file);
503 List<AssemblyLine> lines = new List<AssemblyLine> ();
504 foreach (MethodSource met in sourceFile.Methods) {
505 TargetAddress addr = met.NativeMethod.StartAddress;
506 TargetAddress endAddr = met.NativeMethod.EndAddress;
507 while (addr < endAddr) {
508 SourceAddress line = met.NativeMethod.LineNumberTable.Lookup (addr);
509 AssemblerLine aline = process.MainThread.DisassembleInstruction (met.NativeMethod, addr);
512 lines.Add (new DL.AssemblyLine (addr.Address, aline.Text, line.Row));
514 lines.Add (new DL.AssemblyLine (addr.Address, aline.Text));
515 addr += aline.InstructionSize;
520 lines.Sort (delegate (DL.AssemblyLine l1, DL.AssemblyLine l2) {
521 return l1.SourceLine.CompareTo (l2.SourceLine);
523 return lines.ToArray ();
529 public void Dispose ()
531 MarshalByRefObject mbr
= (MarshalByRefObject
)controller
;
532 ILease lease
= mbr
.GetLifetimeService() as ILease
;
533 lease
.Unregister(this);
536 public void WriteDebuggerOutput (string msg
, params object[] args
)
538 DispatchEvent (delegate {
539 controller
.OnDebuggerOutput (false, string.Format (msg
, args
));
543 public void WriteDebuggerError (Exception ex
)
545 if (ex
is EvaluatorException
)
546 Console
.WriteLine (ex
.Message
);
548 Console
.WriteLine (ex
);
551 public ML
.TargetObject
RuntimeInvoke (EvaluationContext ctx
, ML
.TargetFunctionType function
,
552 ML
.TargetStructObject object_argument
,
553 params ML
.TargetObject
[] param_objects
)
555 return invokeManager
.Invoke (ctx
, function
, object_argument
, param_objects
);
558 DL
.Backtrace
CreateBacktrace (MD
.Thread thread
)
560 List
<MD
.StackFrame
> frames
= new List
<MD
.StackFrame
> ();
561 DateTime t
= DateTime
.Now
;
562 if (!thread
.CurrentFrame
.Language
.IsManaged
) {
563 MD
.Backtrace bt
= thread
.GetBacktrace (MD
.Backtrace
.Mode
.Native
, max_frames
);
565 Console
.WriteLine ("GetBacktrace native time: {0} ms n:{1}", (DateTime
.Now
- t
).TotalMilliseconds
, bt
.Count
);
566 frames
.AddRange (bt
.Frames
);
570 MD
.Backtrace backtrace
= thread
.GetBacktrace (MD
.Backtrace
.Mode
.Managed
, max_frames
);
571 if (backtrace
!= null) {
572 Console
.WriteLine ("GetBacktrace managed time: {0} ms n:{1}", (DateTime
.Now
- t
).TotalMilliseconds
, backtrace
.Count
);
573 frames
.AddRange (backtrace
.Frames
);
576 if (frames
.Count
> 0) {
577 BacktraceWrapper wrapper
= new BacktraceWrapper (frames
.ToArray ());
578 return new DL
.Backtrace (wrapper
);
579 } else if (thread
.CurrentBacktrace
!= null) {
580 BacktraceWrapper wrapper
= new BacktraceWrapper (thread
.CurrentBacktrace
.Frames
);
581 return new DL
.Backtrace (wrapper
);
586 #region ISponsor Members
588 public TimeSpan
Renewal(ILease lease
)
590 return TimeSpan
.FromSeconds(7);
595 private void OnInitialized (MD
.Debugger debugger
, Process process
)
597 Console
.WriteLine (">> OnInitialized");
599 this.process
= process
;
600 this.debugger
= debugger
;
602 guiManager
= process
.StartGUIManager ();
604 //FIXME: conditionally add event handlers
605 process
.TargetOutputEvent
+= OnTargetOutput
;
607 debugger
.ProcessCreatedEvent
+= OnProcessCreatedEvent
;
608 debugger
.ProcessExecdEvent
+= OnProcessExecdEvent
;
609 debugger
.ProcessExitedEvent
+= OnProcessExitedEvent
;
611 debugger
.ThreadCreatedEvent
+= OnThreadCreatedEvent
;
612 debugger
.ThreadExitedEvent
+= OnThreadExitedEvent
;
614 debugger
.TargetExitedEvent
+= OnTargetExitedEvent
;
615 guiManager
.TargetEvent
+= OnTargetEvent
;
618 //guiManager.BreakpointHitHandler = BreakEventCheck;
620 activeThread
= process
.MainThread
;
623 Console
.WriteLine ("<< OnInitialized");
626 void NotifyStarted ()
629 controller
.OnMainProcessCreated(process
.ID
);
630 initializing
= false;
633 void OnTargetOutput (bool is_stderr
, string text
)
635 DispatchEvent (delegate {
636 controller
.OnTargetOutput (is_stderr
, text
);
640 void QueueTask (ST
.WaitCallback cb
)
643 if (stoppedWorkQueue
.Count
> 0)
644 stoppedWorkQueue
.Add (cb
);
650 void ResetTaskQueue ()
653 internalInterruptionRequested
= false;
654 stoppedWorkQueue
.Clear ();
658 void RunWhenStopped (ST
.WaitCallback cb
)
662 if (process
.MainThread
.IsStopped
) {
666 stoppedWorkQueue
.Add (cb
);
668 if (!internalInterruptionRequested
) {
669 internalInterruptionRequested
= true;
670 process
.MainThread
.Stop ();
675 void LogEvent (MD
.TargetEventArgs args
)
677 Console
.WriteLine ("Server OnTargetEvent: {0} stopped:{1} data:{2} internal:{3} queue:{4} thread:{5} running:{6}", args
.Type
, args
.IsStopped
, args
.Data
, internalInterruptionRequested
, stoppedWorkQueue
.Count
, args
.Frame
!= null ? args
.Frame
.Thread
: null, running
);
680 private void OnTargetEvent (MD
.Thread thread
, MD
.TargetEventArgs args
)
688 bool notifyToClient
= args
.IsStopped
|| args
.Type
== MD
.TargetEventType
.UnhandledException
|| args
.Type
== MD
.TargetEventType
.Exception
|| args
.Type
== MD
.TargetEventType
.TargetInterrupted
;
692 bool isStop
= args
.Type
!= MD
.TargetEventType
.FrameChanged
&&
693 args
.Type
!= MD
.TargetEventType
.TargetExited
&&
694 args
.Type
!= MD
.TargetEventType
.TargetRunning
;
699 // The process was stopped, but not as a result of the internal stop request.
700 // Reset the internal request flag, in order to avoid the process to be
701 // automatically restarted
702 if (args
.Type
!= MD
.TargetEventType
.TargetInterrupted
&& args
.Type
!= MD
.TargetEventType
.TargetStopped
)
703 internalInterruptionRequested
= false;
705 notifyToClient
= notifyToClient
&& !internalInterruptionRequested
;
707 if (stoppedWorkQueue
.Count
> 0) {
708 // Execute queued work in another thread with a small delay
709 // since it is not safe to execute it here
710 System
.Threading
.ThreadPool
.QueueUserWorkItem (delegate {
711 System
.Threading
.Thread
.Sleep (50);
714 foreach (ST
.WaitCallback cb
in stoppedWorkQueue
) {
717 stoppedWorkQueue
.Clear ();
718 if (internalInterruptionRequested
) {
719 internalInterruptionRequested
= false;
724 guiManager
.Continue (process
.MainThread
);
725 else if (notifyToClient
)
726 NotifyTargetEvent (thread
, args
);
734 NotifyTargetEvent (thread
, args
);
736 } catch (Exception e
) {
737 Console
.WriteLine ("*** DS.OnTargetEvent1, exception : {0}", e
.ToString ());
741 void NotifyTargetEvent (MD
.Thread thread
, MD
.TargetEventArgs args
)
743 if (args
.Frame
!= null)
744 activeThread
= args
.Frame
.Thread
;
747 if (args
.Type
== MD
.TargetEventType
.TargetStopped
&& ((int)args
.Data
) != 0) {
748 DispatchEvent (delegate {
749 controller
.OnDebuggerOutput (false, string.Format ("Thread {0:x} received signal {1}.\n", args
.Frame
.Thread
.ID
, args
.Data
));
753 DL
.TargetEventType type
;
756 case MD
.TargetEventType
.Exception
: type
= DL
.TargetEventType
.ExceptionThrown
; break;
757 case MD
.TargetEventType
.TargetHitBreakpoint
: type
= DL
.TargetEventType
.TargetHitBreakpoint
; break;
758 case MD
.TargetEventType
.TargetInterrupted
: type
= DL
.TargetEventType
.TargetInterrupted
; break;
759 case MD
.TargetEventType
.TargetSignaled
: type
= DL
.TargetEventType
.TargetSignaled
; break;
760 case MD
.TargetEventType
.TargetStopped
: type
= DL
.TargetEventType
.TargetStopped
; break;
761 case MD
.TargetEventType
.UnhandledException
: type
= DL
.TargetEventType
.UnhandledException
; break;
768 DL
.TargetEventArgs targetArgs
= new DL
.TargetEventArgs (type
);
770 if (args
.Type
!= MD
.TargetEventType
.TargetExited
) {
771 targetArgs
.Backtrace
= CreateBacktrace (thread
);
772 targetArgs
.Thread
= CreateThreadInfo (activeThread
);
775 if ((args
.Type
== MD
.TargetEventType
.UnhandledException
|| args
.Type
== MD
.TargetEventType
.Exception
) && (args
.Data
is TargetAddress
)) {
776 EvaluationContext ctx
= new EvaluationContext (args
.Frame
.Thread
, args
.Frame
, -1);
777 targetArgs
.Exception
= new LiteralValueReference (ctx
, "Exception", args
.Frame
.ExceptionObject
).CreateObjectValue ();
782 DispatchEvent (delegate {
783 controller
.OnTargetEvent (targetArgs
);
785 } catch (Exception e
) {
786 Console
.WriteLine ("*** DS.OnTargetEvent2, exception : {0}", e
.ToString ());
790 void OnStartRunning ()
796 void OnCleanFrameData ()
798 // Dispose all previous remote objects
799 RemoteFrameObject
.DisconnectAll ();
800 CancelRuntimeInvokes ();
803 public void CancelRuntimeInvokes ()
805 asyncEvaluationTracker
.Stop ();
806 invokeManager
.AbortAll ();
807 asyncEvaluationTracker
.WaitForStopped ();
810 public void WaitRuntimeInvokes ()
812 invokeManager
.WaitForAll ();
815 private void OnProcessCreatedEvent (MD
.Debugger debugger
, MD
.Process process
)
817 WriteDebuggerOutput (string.Format ("Process {0} created.\n", process
.ID
));
820 private void OnProcessExitedEvent (MD
.Debugger debugger
, MD
.Process process
)
822 WriteDebuggerOutput (string.Format ("Process {0} exited.\n", process
.ID
));
825 private void OnProcessExecdEvent (MD
.Debugger debugger
, MD
.Process process
)
827 WriteDebuggerOutput (string.Format ("Process {0} execd.\n", process
.ID
));
830 private void OnThreadCreatedEvent (MD
.Debugger debugger
, MD
.Thread thread
)
832 WriteDebuggerOutput (string.Format ("Thread {0} created.\n", thread
.ID
));
835 private void OnThreadExitedEvent (MD
.Debugger debugger
, MD
.Thread thread
)
837 WriteDebuggerOutput (string.Format ("Thread {0} exited.\n", thread
.ID
));
840 private void OnModuleLoadedEvent (Module module
)
842 WriteDebuggerOutput (string.Format ("Module {0} loaded.\n", module
.Name
));
845 private void OnModuleUnLoadedEvent (Module module
)
847 WriteDebuggerOutput (string.Format ("Module {0} unloaded.\n", module
.Name
));
850 private void OnTargetExitedEvent (MD
.Debugger debugger
)
852 DispatchEvent (delegate {
853 controller
.OnDebuggerOutput (false, "Target exited.\n");
854 DL
.TargetEventArgs args
= new DL
.TargetEventArgs (DL
.TargetEventType
.TargetExited
);
855 controller
.OnTargetEvent (args
);
859 void DispatchEvent (ST
.WaitCallback eventCallback
)
862 eventQueue
.Add (eventCallback
);
863 ST
.Monitor
.PulseAll (eventQueue
);
867 void EventDispatcher ()
870 ST
.WaitCallback
[] cbs
;
872 if (eventQueue
.Count
== 0)
873 ST
.Monitor
.Wait (eventQueue
);
874 cbs
= new ST
.WaitCallback
[eventQueue
.Count
];
875 eventQueue
.CopyTo (cbs
, 0);
879 foreach (ST
.WaitCallback wc
in cbs
) {
882 } catch (Exception ex
) {
883 Console
.WriteLine (ex
);