// <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(); } }