internal object SendCommand(SingleSteppingEngine sse, TargetAccessDelegate target, object user_data) { Command command = new Command (sse, target, user_data); if (!engine_event.WaitOne (WaitTimeout, false)) throw new TargetException (TargetError.NotStopped); event_queue.Lock (); engine_event.Reset (); current_command = command; event_queue.Signal (); event_queue.Unlock (); engine_event.WaitOne (); if (command.Result is Exception) throw (Exception) command.Result; else return command.Result; }
// <summary> // The heart of the SingleSteppingEngine. This runs in a background // thread and processes stepping commands and events. // // For each application we're debugging, there is just one SingleSteppingEngine, // no matter how many threads the application has. The engine is using one single // event loop which is processing commands from the user and events from all of // the application's threads. // </summary> void engine_thread_main() { Report.Debug (DebugFlags.Wait, "ThreadManager waiting"); event_queue.Wait (); Report.Debug (DebugFlags.Wait, "ThreadManager done waiting"); if (abort_requested) { Report.Debug (DebugFlags.Wait, "Engine thread abort requested"); return; } int status; SingleSteppingEngine event_engine; Command command; Report.Debug (DebugFlags.Wait, "ThreadManager woke up: {0} {1:x} {2}", current_event, current_event_status, current_command); event_engine = current_event; status = current_event_status; current_event = null; current_event_status = 0; command = current_command; current_command = null; if (event_engine != null) { try { Report.Debug (DebugFlags.Wait, "ThreadManager {0} process event: {1}", DebuggerWaitHandle.CurrentThread, event_engine); event_engine.ProcessEvent (status); Report.Debug (DebugFlags.Wait, "ThreadManager {0} process event done: {1}", DebuggerWaitHandle.CurrentThread, event_engine); } catch (ST.ThreadAbortException) { ; } catch (Exception e) { Report.Debug (DebugFlags.Wait, "ThreadManager caught exception: {0}", e); Console.WriteLine ("EXCEPTION: {0}", e); } check_pending_events (); if (command == null) engine_event.Set (); RequestWait (); } if (command == null) return; // These are synchronous commands; ie. the caller blocks on us // until we finished the command and sent the result. if (command.Type == CommandType.TargetAccess) { try { if(command.Engine.Inferior != null) command.Result = command.Engine.Invoke ( (TargetAccessDelegate) command.Data1, command.Data2); } catch (ST.ThreadAbortException) { return; } catch (Exception ex) { command.Result = ex; } check_pending_events (); engine_event.Set (); } else if (command.Type == CommandType.CreateProcess) { try { ProcessStart start = (ProcessStart) command.Data1; Process process = new Process (this, start); processes.Add (process); CommandResult result = process.StartApplication (); RequestWait (); command.Result = new KeyValuePair<CommandResult,Process> (result, process); } catch (ST.ThreadAbortException) { return; } catch (Exception ex) { command.Result = ex; } engine_event.Set (); } else { throw new InvalidOperationException (); } }
public Process StartApplication(ProcessStart start, out CommandResult result) { Command command = new Command (CommandType.CreateProcess, start); if (!engine_event.WaitOne (WaitTimeout, false)) throw new TargetException (TargetError.NotStopped); event_queue.Lock (); engine_event.Reset (); current_command = command; event_queue.Signal (); event_queue.Unlock (); engine_event.WaitOne (); if (command.Result is Exception) throw (Exception) command.Result; else { var pair = (KeyValuePair<CommandResult,Process>) command.Result; result = pair.Key; return pair.Value; } }