* Makefile.am:
[monodevelop.git] / extras / MonoDevelop.Debugger.Mdb / Mono.Debugging.Server.Mdb / DebuggerServer.cs
bloba659e7f8bef9f083a33661fe551113be77aec155
1 using System;
2 using System.Collections.Generic;
3 using System.Runtime.InteropServices;
4 using System.Runtime.Remoting.Lifetime;
5 using System.Text;
6 using ST = System.Threading;
8 using Mono.Debugger;
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;
23 MD.Debugger debugger;
24 MD.DebuggerSession session;
25 MD.Process process;
26 MD.GUIManager guiManager;
27 int max_frames;
28 bool internalInterruptionRequested;
29 List<ST.WaitCallback> stoppedWorkQueue = new List<ST.WaitCallback> ();
30 List<ST.WaitCallback> eventQueue = new List<ST.WaitCallback> ();
31 bool initializing;
32 bool running;
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)
53 this.controller = dc;
54 MarshalByRefObject mbr = (MarshalByRefObject)controller;
55 ILease lease = mbr.GetLifetimeService() as ILease;
56 lease.Register(this);
57 max_frames = 100;
59 ST.Thread t = new ST.Thread ((ST.ThreadStart)EventDispatcher);
60 t.IsBackground = true;
61 t.Start ();
63 invokeManager = new RuntimeInvokeManager ();
64 asyncEvaluationTracker = new AsyncEvaluationTracker ();
67 public override object InitializeLifetimeService ()
69 return null;
72 public ExpressionEvaluator Evaluator {
73 get { return evaluator; }
76 public AsyncEvaluationTracker AsyncEvaluationTracker {
77 get {
78 return asyncEvaluationTracker;
82 #region IDebugger Members
84 public void Run (DL.DebuggerStartInfo startInfo)
86 try {
87 if (startInfo == null)
88 throw new ArgumentNullException ("startInfo");
90 Report.Initialize ();
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);
101 NotifyStarted ();
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 ());
122 throw;
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 {
142 NotifyStarted ();
146 public void Detach ()
148 CancelRuntimeInvokes ();
149 RunWhenStopped (delegate {
150 try {
151 debugger.Detach ();
152 } catch (Exception ex) {
153 Console.WriteLine (ex);
154 } finally {
155 running = false;
160 public void Stop ()
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;
169 else
170 guiManager.Stop (process.MainThread);
174 public void Exit ()
176 CancelRuntimeInvokes ();
177 ResetTaskQueue ();
178 debugger.Kill ();
179 running = false;
182 int ncc = 0;
183 public void NextLine ()
185 if (running)
186 throw new InvalidOperationException ("Target already running");
187 OnStartRunning ();
188 guiManager.StepOver (activeThread);
191 public void StepLine ()
193 if (running)
194 throw new InvalidOperationException ("Target already running");
195 OnStartRunning ();
196 guiManager.StepInto (activeThread);
199 public void StepInstruction ()
201 if (running)
202 throw new InvalidOperationException ("Target already running");
203 OnStartRunning ();
204 activeThread.StepInstruction ();
207 public void NextInstruction ()
209 if (running)
210 throw new InvalidOperationException ("Target already running");
211 OnStartRunning ();
212 activeThread.NextInstruction ();
215 public void Finish ()
217 if (running)
218 throw new InvalidOperationException ("Target already running");
219 OnStartRunning ();
220 guiManager.StepOut (activeThread);
223 public void Continue ()
225 if (running)
226 throw new InvalidOperationException ("Target already running");
227 OnStartRunning ();
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;
237 MD.Event ev = null;
239 if (bp != null) {
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);
248 if (exc != null)
249 break;
251 if (exc == null)
252 throw new Exception ("Unknown exception type.");
253 ev = session.InsertExceptionCatchPoint (process.MainThread, ThreadGroup.Global, exc);
256 ev.IsEnabled = enable;
258 if (!initializing) {
259 RunWhenStopped (delegate {
260 try {
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);
272 if (ob != null)
273 lastConditionValue [ev.Index] = evaluator.TargetObjectToExpression (ctx, ob);
276 events [ev.Index] = be;
277 return ev.Index;
280 public void RemoveBreakEvent (int handle)
282 CancelRuntimeInvokes ();
283 RunWhenStopped (delegate {
284 try {
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);
299 if (enable)
300 ev.Activate (process.MainThread);
301 else
302 ev.Deactivate (process.MainThread);
306 public object UpdateBreakEvent (object handle, DL.BreakEvent bp)
308 events [(int)handle] = bp;
309 return handle;
312 bool BreakEventCheck (MD.TargetEventArgs args)
314 MD.StackFrame frame = args.Frame;
315 if (!(args.Data is int))
316 return true;
318 int eventHandle = (int) args.Data;
320 DL.BreakEvent be;
321 if (!events.TryGetValue (eventHandle, out be))
322 return true;
324 // Check hit count
325 if (be.HitCount > 0) {
326 be.HitCount--;
327 DispatchEvent (delegate {
328 NotifyBreakEventUpdate (eventHandle, be.HitCount, null);
330 return false;
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);
337 if (val == null)
338 return false;
339 if (bp.BreakIfConditionChanges) {
340 string current = evaluator.TargetObjectToExpression (ctx, val);
341 string last;
342 bool found = lastConditionValue.TryGetValue (eventHandle, out last);
343 lastConditionValue [eventHandle] = current;
344 if (!found || last == current)
345 return false;
346 } else {
347 ML.TargetFundamentalObject fob = val as ML.TargetFundamentalObject;
348 if (fob == null)
349 return false;
350 object ob = fob.GetObject (frame.Thread);
351 if (!(ob is bool) || !(bool)ob)
352 return false;
356 switch (be.HitAction) {
357 case HitAction.Break:
358 return true;
359 case HitAction.CustomAction:
360 return controller.OnCustomBreakpointAction (be.CustomActionId, eventHandle);
361 case HitAction.PrintExpression:
362 if (string.IsNullOrEmpty (be.TraceExpression) || frame == null)
363 return false;
364 ML.TargetObject val = EvaluateExp (ctx, be.TraceExpression);
365 if (val != null) {
366 string str = evaluator.TargetObjectToString (ctx, val);
367 DispatchEvent (delegate {
368 controller.OnTargetOutput (false, str + "\n");
369 NotifyBreakEventUpdate (eventHandle, -1, str);
372 return false;
374 return false;
377 ML.TargetObject EvaluateExp (EvaluationContext ctx, string exp)
379 ValueReference var;
380 try {
381 EvaluationOptions ops = new EvaluationOptions ();
382 ops.CanEvaluateMethods = true;
383 var = (ValueReference) Server.Instance.Evaluator.Evaluate (ctx, exp, ops);
384 return var.Value;
385 } catch {
386 return null;
390 void NotifyBreakEventUpdate (int eventHandle, int hitCount, string lastTrace)
392 bool notify = false;
394 lock (breakUpdates)
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;
400 notify = true;
401 } else {
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)
419 wc (null);
424 if (notify)
425 controller.UpdateBreakpoint (eventHandle, hitCount, lastTrace);
428 public ThreadInfo[] GetThreads (int processId)
430 MD.Process p = GetProcess (processId);
431 if (p == null)
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);
436 list.Add (ct);
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)
451 string loc;
452 if (t.CurrentFrame != null && t.CurrentFrame.SourceLocation != null) {
453 loc = t.CurrentFrame.ToString ();
454 } else
455 loc = "<Unknown>";
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);
465 else
466 return null;
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);
477 if (proc != null) {
478 foreach (MD.Thread t in proc.GetThreads ()) {
479 if (t.ID == threadId)
480 return t;
483 return null;
486 MD.Process GetProcess (int id)
488 foreach (MD.Process p in debugger.Processes) {
489 if (p.ID == id)
490 return p;
492 return null;
495 public AssemblyLine[] DisassembleFile (string file)
497 CancelRuntimeInvokes ();
499 // Not working yet
500 return null;
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);
510 if (aline != null) {
511 if (line != null)
512 lines.Add (new DL.AssemblyLine (addr.Address, aline.Text, line.Row));
513 else
514 lines.Add (new DL.AssemblyLine (addr.Address, aline.Text));
515 addr += aline.InstructionSize;
516 } else
517 addr++;
520 lines.Sort (delegate (DL.AssemblyLine l1, DL.AssemblyLine l2) {
521 return l1.SourceLine.CompareTo (l2.SourceLine);
523 return lines.ToArray ();
527 #endregion
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);
547 else
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);
564 if (bt != null) {
565 Console.WriteLine ("GetBacktrace native time: {0} ms n:{1}", (DateTime.Now - t).TotalMilliseconds, bt.Count);
566 frames.AddRange (bt.Frames);
568 } else {
569 t = DateTime.Now;
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);
583 return null;
586 #region ISponsor Members
588 public TimeSpan Renewal(ILease lease)
590 return TimeSpan.FromSeconds(7);
593 #endregion
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;
617 // Not supported
618 //guiManager.BreakpointHitHandler = BreakEventCheck;
620 activeThread = process.MainThread;
621 running = true;
623 Console.WriteLine ("<< OnInitialized");
626 void NotifyStarted ()
628 initializing = true;
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)
642 lock (debugger) {
643 if (stoppedWorkQueue.Count > 0)
644 stoppedWorkQueue.Add (cb);
645 else
646 cb (null);
650 void ResetTaskQueue ()
652 lock (debugger) {
653 internalInterruptionRequested = false;
654 stoppedWorkQueue.Clear ();
658 void RunWhenStopped (ST.WaitCallback cb)
660 lock (debugger)
662 if (process.MainThread.IsStopped) {
663 cb (null);
664 return;
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)
682 try {
683 if (!running) {
684 LogEvent (args);
685 return;
688 bool notifyToClient = args.IsStopped || args.Type == MD.TargetEventType.UnhandledException || args.Type == MD.TargetEventType.Exception || args.Type == MD.TargetEventType.TargetInterrupted;
690 LogEvent (args);
692 bool isStop = args.Type != MD.TargetEventType.FrameChanged &&
693 args.Type != MD.TargetEventType.TargetExited &&
694 args.Type != MD.TargetEventType.TargetRunning;
696 if (isStop) {
698 lock (debugger) {
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);
712 bool resume = false;
713 lock (debugger) {
714 foreach (ST.WaitCallback cb in stoppedWorkQueue) {
715 cb (null);
717 stoppedWorkQueue.Clear ();
718 if (internalInterruptionRequested) {
719 internalInterruptionRequested = false;
720 resume = true;
723 if (resume)
724 guiManager.Continue (process.MainThread);
725 else if (notifyToClient)
726 NotifyTargetEvent (thread, args);
728 return;
733 if (notifyToClient)
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;
746 try {
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;
755 switch (args.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;
762 default:
763 return;
766 OnCleanFrameData ();
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 ();
780 running = false;
782 DispatchEvent (delegate {
783 controller.OnTargetEvent (targetArgs);
785 } catch (Exception e) {
786 Console.WriteLine ("*** DS.OnTargetEvent2, exception : {0}", e.ToString ());
790 void OnStartRunning ()
792 OnCleanFrameData ();
793 running = true;
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)
861 lock (eventQueue) {
862 eventQueue.Add (eventCallback);
863 ST.Monitor.PulseAll (eventQueue);
867 void EventDispatcher ()
869 while (true) {
870 ST.WaitCallback[] cbs;
871 lock (eventQueue) {
872 if (eventQueue.Count == 0)
873 ST.Monitor.Wait (eventQueue);
874 cbs = new ST.WaitCallback [eventQueue.Count];
875 eventQueue.CopyTo (cbs, 0);
876 eventQueue.Clear ();
879 foreach (ST.WaitCallback wc in cbs) {
880 try {
881 wc (null);
882 } catch (Exception ex) {
883 Console.WriteLine (ex);