Beispiel #1
0
        internal SingleSteppingEngine GetEngineByTID(Inferior inferior, long tid)
        {
            foreach (SingleSteppingEngine engine in thread_hash.Values)
            {
                if (engine.TID == tid)
                {
                    return(engine);
                }
            }

            if (thread_db == null)
            {
                Report.Error("Failed to initialize thread_db on {0}: {1}",
                             start.CommandLine, start);
                return(null);
            }

            SingleSteppingEngine result = null;

            thread_db.GetThreadInfo(inferior, delegate(int t_lwp, long t_tid) {
                if (tid != t_tid)
                {
                    return;
                }
                result = (SingleSteppingEngine)thread_hash [t_lwp];
            });

            if (result == null)
            {
                Report.Error("Cannot find thread {0:x} in {1}",
                             tid, start.CommandLine);
            }

            return(result);
        }
Beispiel #2
0
        internal void ChildForked(Inferior inferior, int pid)
        {
            Process new_process = new Process(this, pid);

            new_process.ProcessStart.StopInMain = false;

            Inferior new_inferior = Inferior.CreateInferior(
                manager, new_process, new_process.ProcessStart);

            new_inferior.InitializeThread(pid);

            if (!manager.Debugger.Configuration.FollowFork)
            {
                new_inferior.DetachAfterFork();
                return;
            }

            SingleSteppingEngine new_thread = new SingleSteppingEngine(
                manager, new_process, new_inferior, pid);

            Report.Debug(DebugFlags.Threads, "Child forked: {0} {1}", pid, new_thread);

            new_process.main_thread = new_thread;

            manager.Debugger.OnProcessCreatedEvent(new_process);
            new_process.OnThreadCreatedEvent(new_thread);

            CommandResult result = new_process.CloneParentOperation(new_thread);

            new_thread.StartForkedChild(result);
        }
Beispiel #3
0
        internal CommandResult StartApplication()
        {
            SingleSteppingEngine engine = new SingleSteppingEngine(manager, this, start);

            initialized = true;

            this.main_thread           = engine;
            engine.Thread.ThreadFlags |= Thread.Flags.StopOnExit;

            if (thread_hash.Contains(engine.PID))
            {
                thread_hash [engine.PID] = engine;
            }
            else
            {
                thread_hash.Add(engine.PID, engine);
            }
            session.MainThreadGroup.AddThread(engine.Thread.ID);

            session.OnMainProcessCreated(this);
            manager.Debugger.OnMainProcessCreatedEvent(this);

            CommandResult result = Debugger.StartOperation(start.Session.Config.ThreadingModel, engine);

            return(engine.StartApplication(result));
        }
Beispiel #4
0
        CommandResult CloneParentOperation(SingleSteppingEngine new_thread)
        {
            if (parent.current_state == ProcessState.SingleThreaded)
            {
                current_state = ProcessState.SingleThreaded;
                return(new ThreadCommandResult(new_thread.Thread));
            }

            if (parent.current_state != ProcessState.Running)
            {
                throw new InternalError();
            }

            current_state = ProcessState.Running;
            if ((parent.current_operation.ThreadingModel & ThreadingModel.ThreadingMode) == ThreadingModel.Global)
            {
                current_operation = parent.current_operation;
            }
            else if ((parent.current_operation.ThreadingModel & ThreadingModel.ThreadingMode) == ThreadingModel.Process)
            {
                current_operation = new ProcessCommandResult(this, parent.current_operation.ThreadingModel);
            }
            else
            {
                throw new InternalError();
            }

            return(current_operation);
        }
Beispiel #5
0
        internal void ThreadCreated(Inferior inferior, int pid, bool do_attach, bool resume_thread)
        {
            Inferior new_inferior = inferior.CreateThread(pid, do_attach);

            SingleSteppingEngine new_thread = new SingleSteppingEngine(manager, this, new_inferior, pid);

            Report.Debug(DebugFlags.Threads, "Thread created: {0} {1} {2}", pid, new_thread, do_attach);

            if (mono_manager != null)
            {
                mono_manager.ThreadCreated(new_thread);
            }

            if (!do_attach && !is_execed)
            {
                get_thread_info(inferior, new_thread);
            }
            OnThreadCreatedEvent(new_thread);

            if (resume_thread)
            {
                CommandResult result = current_operation != null ?
                                       current_operation : new ThreadCommandResult(new_thread.Thread);
                new_thread.StartThread(result);
            }
            else
            {
                new_thread.StartSuspended();
            }
        }
Beispiel #6
0
        internal CommandResult StartOperation(ThreadingModel model, SingleSteppingEngine caller)
        {
            if (!ThreadManager.InBackgroundThread)
            {
                throw new InternalError();
            }

            if ((current_state != ProcessState.Stopped) && (current_state != ProcessState.SingleThreaded))
            {
                throw new TargetException(TargetError.NotStopped);
            }

            if ((model & ThreadingModel.ThreadingMode) == ThreadingModel.Single)
            {
                current_state = ProcessState.SingleThreaded;
                if ((model & ThreadingModel.ResumeThreads) != 0)
                {
                    ResumeUserThreads(model, caller);
                }
                return(new ThreadCommandResult(caller.Thread));
            }
            else if ((model & ThreadingModel.ThreadingMode) != ThreadingModel.Process)
            {
                throw new ArgumentException();
            }

            lock (this) {
                current_state = ProcessState.Running;
                stopped_event.Reset();
                current_operation = new ProcessCommandResult(this, model);
            }

            ResumeUserThreads(model, caller);
            return(current_operation);
        }
Beispiel #7
0
        internal void OperationCompleted(SingleSteppingEngine caller, TargetEventArgs result, ThreadingModel model)
        {
            if (!ThreadManager.InBackgroundThread && Inferior.HasThreadEvents)
            {
                throw new InternalError();
            }

            if (current_state == ProcessState.Stopping)
            {
                return;
            }
            else if (current_state != ProcessState.Running)
            {
                throw new InternalError();
            }

            if ((result != null) && (caller != main_thread) &&
                ((result.Type == TargetEventType.TargetExited) || (result.Type == TargetEventType.TargetSignaled)))
            {
                return;
            }

            current_state = ProcessState.Stopping;
            SuspendUserThreads(model, caller);

            lock (this) {
                current_state = ProcessState.Stopped;
                current_operation.Completed();
                current_operation = null;
                stopped_event.Set();
            }
        }
Beispiel #8
0
        void SuspendUserThreads(ThreadingModel model, SingleSteppingEngine caller)
        {
            Report.Debug(DebugFlags.Threads,
                         "Suspending user threads: {0} {1}", model, caller);

            foreach (SingleSteppingEngine engine in thread_hash.Values)
            {
                Report.Debug(DebugFlags.Threads, "  check user thread: {0} {1}",
                             engine, engine.Thread.ThreadFlags);
                if (engine == caller)
                {
                    continue;
                }
                if (((engine.Thread.ThreadFlags & Thread.Flags.Immutable) != 0) &&
                    ((model & ThreadingModel.StopImmutableThreads) == 0))
                {
                    continue;
                }
                if (((engine.Thread.ThreadFlags & Thread.Flags.Daemon) != 0) &&
                    ((model & ThreadingModel.StopDaemonThreads) == 0))
                {
                    continue;
                }
                engine.SuspendUserThread();
            }

            Report.Debug(DebugFlags.Threads,
                         "Done suspending user threads: {0} {1}", model, caller);
        }
Beispiel #9
0
        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);
            }
        }
Beispiel #10
0
        void check_pending_events()
        {
            SingleSteppingEngine[] list = new SingleSteppingEngine [pending_events.Count];
            pending_events.Keys.CopyTo(list, 0);

            for (int i = 0; i < list.Length; i++)
            {
                SingleSteppingEngine engine = list [i];
                if (engine.Process.HasThreadLock)
                {
                    continue;
                }

                Inferior.ChildEvent cevent = (Inferior.ChildEvent)pending_events [engine];
                pending_events.Remove(engine);

                try {
                    Report.Debug(DebugFlags.Wait,
                                 "ThreadManager {0} process pending event: {1} {2}",
                                 DebuggerWaitHandle.CurrentThread, engine, cevent);
                    engine.ReleaseThreadLock(cevent);
                    Report.Debug(DebugFlags.Wait,
                                 "ThreadManager {0} process pending event done: {1}",
                                 DebuggerWaitHandle.CurrentThread, engine);
                } catch (ST.ThreadAbortException) {
                    ;
                } catch (Exception e) {
                    Report.Debug(DebugFlags.Wait,
                                 "ThreadManager caught exception: {0}", e);
                }
            }
        }
Beispiel #11
0
        void get_thread_info(Inferior inferior, SingleSteppingEngine engine)
        {
            if (thread_db == null)
            {
                if (mono_manager == null)
                {
                    return;
                }
                Report.Error("Failed to initialize thread_db on {0}: {1} {2}",
                             start.CommandLine, start, Environment.StackTrace);
                throw new InternalError();
            }

            bool found = false;

            thread_db.GetThreadInfo(inferior, delegate(int lwp, long tid) {
                if (lwp != engine.PID)
                {
                    return;
                }

                engine.SetTID(tid);
                found = true;
            });

            if (!found)
            {
                Report.Error("Cannot find thread {0:x} in {1}",
                             engine.PID, start.CommandLine);
            }
        }
Beispiel #12
0
 internal override void Completed(SingleSteppingEngine sse, TargetEventArgs args)
 {
     Host.OperationCompleted(sse, args, ThreadingModel);
     if (args != null)
     {
         Host.SendResult(sse, args);
     }
 }
Beispiel #13
0
 internal void ThreadCreated(SingleSteppingEngine sse)
 {
     sse.Inferior.SetRuntimeInfo(mono_runtime_info);
     if (!MonoDebuggerInfo.CheckRuntimeVersion(81, 3) && !process.IsAttached)
     {
         if (++index < 3)
         {
             sse.Thread.ThreadFlags |= Thread.Flags.Daemon | Thread.Flags.Immutable;
         }
     }
     else
     {
         sse.Thread.ThreadFlags |= Thread.Flags.Daemon | Thread.Flags.Immutable;
     }
 }
Beispiel #14
0
 void check_thread_flags(SingleSteppingEngine engine, ThreadFlags flags)
 {
     if ((flags & (ThreadFlags.Internal | ThreadFlags.ThreadPool)) != ThreadFlags.Internal)
     {
         engine.Thread.ThreadFlags &= ~(Thread.Flags.Daemon | Thread.Flags.Immutable);
         if (engine != process.MainThreadServant)
         {
             process.Debugger.OnManagedThreadCreatedEvent(engine.Thread);
         }
     }
     else if ((flags & ThreadFlags.ThreadPool) != 0)
     {
         engine.Thread.ThreadFlags &= ~Thread.Flags.Immutable;
     }
 }
Beispiel #15
0
        void OperationCompleted(SingleSteppingEngine caller, TargetEventArgs result, ThreadingModel model)
        {
            if (!ThreadManager.InBackgroundThread)
            {
                throw new InternalError();
            }

            foreach (Process process in process_hash.Values)
            {
                process.OperationCompleted(caller, result, model);
            }

            lock (this) {
                current_operation = null;
                stopped_event.Set();
            }
        }
Beispiel #16
0
        internal void ReleaseGlobalThreadLock(SingleSteppingEngine caller)
        {
            Report.Debug(DebugFlags.Threads,
                         "Releasing global thread lock: {0}", caller);

            foreach (ThreadServant thread in thread_hash.Values)
            {
                if (thread == caller)
                {
                    continue;
                }
                thread.ReleaseThreadLock();
            }
            has_thread_lock = false;
            thread_lock_mutex.Unlock();
            Report.Debug(DebugFlags.Threads,
                         "Released global thread lock: {0}", caller);
        }
Beispiel #17
0
        void ResumeUserThreads(ThreadingModel model, SingleSteppingEngine caller)
        {
            Report.Debug(DebugFlags.Threads,
                         "Resuming user threads: {0}", caller);

            foreach (SingleSteppingEngine engine in thread_hash.Values)
            {
                if (engine == caller)
                {
                    continue;
                }
                if ((engine.Thread.ThreadFlags & Thread.Flags.AutoRun) == 0)
                {
                    continue;
                }
                if (((engine.Thread.ThreadFlags & Thread.Flags.Immutable) != 0) &&
                    ((model & ThreadingModel.StopImmutableThreads) == 0))
                {
                    continue;
                }
                if (((engine.Thread.ThreadFlags & Thread.Flags.Daemon) != 0) &&
                    ((model & ThreadingModel.StopDaemonThreads) == 0))
                {
                    continue;
                }

                CommandResult result;
                if (current_operation != null)
                {
                    result = current_operation;
                }
                else
                {
                    result = new ThreadCommandResult(engine.Thread);
                }

                engine.ResumeUserThread(result);
            }

            Report.Debug(DebugFlags.Threads,
                         "Resumed user threads: {0}", caller);
        }
Beispiel #18
0
        internal void StartGlobalOperation(ThreadingModel model, SingleSteppingEngine caller, OperationCommandResult operation)
        {
            if (!ThreadManager.InBackgroundThread)
            {
                throw new InternalError();
            }

            if ((current_state != ProcessState.Stopped) && (current_state != ProcessState.SingleThreaded))
            {
                throw new TargetException(TargetError.NotStopped);
            }

            lock (this) {
                current_state = ProcessState.Running;
                stopped_event.Reset();
                current_operation = operation;
            }

            ResumeUserThreads(model, caller);
        }
Beispiel #19
0
 public void Kill()
 {
     if (!Inferior.HasThreadEvents)
     {
         SingleSteppingEngine[] sses = new SingleSteppingEngine [thread_hash.Count];
         thread_hash.Values.CopyTo(sses, 0);
         foreach (SingleSteppingEngine sse in sses)
         {
             sse.SetKilledFlag();
         }
         foreach (SingleSteppingEngine sse in sses)
         {
             sse.Kill();
         }
     }
     else
     {
         main_thread.Kill();
     }
 }
Beispiel #20
0
        internal CommandResult StartOperation(ThreadingModel model, SingleSteppingEngine caller)
        {
            if (!ThreadManager.InBackgroundThread)
            {
                throw new InternalError();
            }

            if ((model & ThreadingModel.ThreadingMode) == ThreadingModel.Default)
            {
                if (Inferior.HasThreadEvents)
                {
                    model |= ThreadingModel.Single;
                }
                else
                {
                    model |= ThreadingModel.Process;
                }
            }

            if ((model & ThreadingModel.ThreadingMode) != ThreadingModel.Global)
            {
                return(caller.Process.StartOperation(model, caller));
            }

            if (current_operation != null)
            {
                throw new TargetException(TargetError.NotStopped);
            }

            lock (this) {
                stopped_event.Reset();
                current_operation = new GlobalCommandResult(this, model);
            }

            foreach (Process process in process_hash.Values)
            {
                process.StartGlobalOperation(model, caller, current_operation);
            }

            return(current_operation);
        }
Beispiel #21
0
        internal virtual void Completed(SingleSteppingEngine sse, TargetEventArgs args)
        {
            if ((args != null) && ((args.Type == TargetEventType.TargetExited) || (args.Type == TargetEventType.TargetSignaled)))
            {
                if ((sse.Thread.ThreadFlags & Thread.Flags.StopOnExit) == 0)
                {
                    Host.SendResult(sse, args);
                    return;
                }
            }

            if (!IsCompleted)
            {
                IsCompleted = true;
                if (args != null)
                {
                    Host.SendResult(sse, args);
                }
                Host.OperationCompleted(sse, args, ThreadingModel);
            }
        }
Beispiel #22
0
        internal void InitializeThreads(Inferior inferior, bool resume_threads)
        {
            if (thread_db != null)
            {
                return;
            }

            thread_db = ThreadDB.Create(this, inferior);
            if (thread_db == null)
            {
                if (!IsManaged)
                {
                    return;
                }

                Report.Error("Failed to initialize thread_db on {0}", start.CommandLine);
                throw new TargetException(TargetError.CannotStartTarget,
                                          "Failed to initialize thread_db on {0}", start.CommandLine);
            }

            int[] threads = inferior.GetThreads();
            foreach (int thread in threads)
            {
                if (thread_hash.Contains(thread))
                {
                    continue;
                }
                ThreadCreated(inferior, thread, Inferior.HasThreadEvents, resume_threads);
            }

            thread_db.GetThreadInfo(inferior, delegate(int lwp, long tid) {
                SingleSteppingEngine engine = (SingleSteppingEngine)thread_hash [lwp];
                if (engine == null)
                {
                    Report.Error("Unknown thread {0} in {1}", lwp, start.CommandLine);
                    return;
                }
                engine.SetTID(tid);
            });
        }
Beispiel #23
0
        // <summary>
        //   Stop all currently running threads without sending any notifications.
        //   The threads are automatically resumed to their previos state when
        //   ReleaseGlobalThreadLock() is called.
        // </summary>
        internal void AcquireGlobalThreadLock(SingleSteppingEngine caller)
        {
            if (has_thread_lock)
            {
                throw new InternalError("Recursive thread lock");
            }

            thread_lock_mutex.Lock();
            Report.Debug(DebugFlags.Threads,
                         "Acquiring global thread lock: {0}", caller);
            has_thread_lock = true;
            foreach (ThreadServant thread in thread_hash.Values)
            {
                if (thread == caller)
                {
                    continue;
                }
                thread.AcquireThreadLock();
            }
            Report.Debug(DebugFlags.Threads,
                         "Done acquiring global thread lock: {0}",
                         caller);
        }
Beispiel #24
0
        internal bool HandleChildEvent(SingleSteppingEngine engine, Inferior inferior,
                                       ref Inferior.ChildEvent cevent, out bool resume_target)
        {
            if (cevent.Type == Inferior.ChildEventType.NONE)
            {
                resume_target = true;
                return(true);
            }

            if (cevent.Type == Inferior.ChildEventType.CHILD_CREATED_THREAD)
            {
                int pid = (int)cevent.Argument;
                inferior.Process.ThreadCreated(inferior, pid, false, true);
                if (pending_sigstops.ContainsKey(pid))
                {
                    pending_sigstops.Remove(pid);
                }
                resume_target = true;
                return(true);
            }

            if (cevent.Type == Inferior.ChildEventType.CHILD_FORKED)
            {
                inferior.Process.ChildForked(inferior, (int)cevent.Argument);
                resume_target = true;
                return(true);
            }

            if (cevent.Type == Inferior.ChildEventType.CHILD_EXECD)
            {
                thread_hash.Remove(engine.PID);
                engine_hash.Remove(engine.ID);
                inferior.Process.ChildExecd(engine, inferior);
                resume_target = false;
                return(true);
            }

            if (cevent.Type == Inferior.ChildEventType.CHILD_STOPPED)
            {
                if (cevent.Argument == inferior.SIGCHLD)
                {
                    cevent = new Inferior.ChildEvent(
                        Inferior.ChildEventType.CHILD_STOPPED, 0, 0, 0);
                    resume_target = true;
                    return(true);
                }
                else if (inferior.Has_SIGWINCH && (cevent.Argument == inferior.SIGWINCH))
                {
                    resume_target = true;
                    return(true);
                }
                else if (inferior.HasSignals && (cevent.Argument == inferior.Kernel_SIGRTMIN + 1))
                {
                    // __SIGRTMIN and __SIGRTMIN+1 are used internally by the threading library
                    resume_target = true;
                    return(true);
                }
            }

            if (inferior.Process.OperatingSystem.CheckForPendingMonoInit(inferior))
            {
                resume_target = true;
                return(true);
            }

            bool retval = false;

            resume_target = false;
            if (inferior.Process.MonoManager != null)
            {
                retval = inferior.Process.MonoManager.HandleChildEvent(
                    engine, inferior, ref cevent, out resume_target);
            }

            if ((cevent.Type == Inferior.ChildEventType.CHILD_EXITED) ||
                (cevent.Type == Inferior.ChildEventType.CHILD_SIGNALED))
            {
                thread_hash.Remove(engine.PID);
                engine_hash.Remove(engine.ID);
                engine.OnThreadExited(cevent);
                resume_target = false;
                return(true);
            }

            return(retval);
        }
Beispiel #25
0
 internal override void OnExecd(SingleSteppingEngine new_thread)
 {
     Thread = new_thread.Thread;
 }
Beispiel #26
0
 void IOperationHost.SendResult(SingleSteppingEngine sse, TargetEventArgs args)
 {
     sse.Process.Debugger.OnTargetEvent(sse.Client, args);
 }
Beispiel #27
0
 void IOperationHost.OperationCompleted(SingleSteppingEngine sse, TargetEventArgs args, ThreadingModel model)
 {
 }
Beispiel #28
0
        bool wait_thread_main()
        {
            Report.Debug(DebugFlags.Wait, "Wait thread sleeping");
            wait_event.WaitOne();
            waiting = true;

again:
            Report.Debug(DebugFlags.Wait, "Wait thread again");

            int pid = 0, status = 0;

            if (abort_requested)
            {
                Report.Debug(DebugFlags.Wait,
                             "Wait thread abort requested");

                //
                // Reap all our children.
                //

                do
                {
                    Report.Debug(DebugFlags.Wait,
                                 "Wait thread reaping children");
                    pid = mono_debugger_server_global_wait(out status);
                    Report.Debug(DebugFlags.Wait,
                                 "Wait thread received event: {0} {1:x}",
                                 pid, status);
                } while (pid > 0);

                Report.Debug(DebugFlags.Wait,
                             "Wait thread done");

                return(false);
            }

            if (DateTime.Now - last_pending_sigstop > new TimeSpan(0, 2, 30))
            {
                foreach (int pending in pending_sigstops.Keys)
                {
                    Report.Error("Got SIGSTOP from unknown PID {0}!", pending);
                }

                pending_sigstops.Clear();
                last_pending_sigstop = DateTime.Now;
            }

            Report.Debug(DebugFlags.Wait, "Wait thread waiting");

            //
            // Wait until we got an event from the target or a command from the user.
            //

            pid = mono_debugger_server_global_wait(out status);

            Report.Debug(DebugFlags.Wait,
                         "Wait thread received event: {0} {1:x}",
                         pid, status);

            //
            // Note: `pid' is basically just an unique number which identifies the
            //       SingleSteppingEngine of this event.
            //

            if (abort_requested || (pid <= 0))
            {
                return(true);
            }

            if (!Inferior.HasThreadEvents)
            {
                int arg;
                Inferior.ChildEventType etype  = mono_debugger_server_dispatch_simple(status, out arg);
                SingleSteppingEngine    engine = (SingleSteppingEngine)thread_hash [pid];
                if (etype == Inferior.ChildEventType.CHILD_EXITED)
                {
                    if (engine != null)
                    {
                        SingleSteppingEngine[] sses = new SingleSteppingEngine [thread_hash.Count];
                        thread_hash.Values.CopyTo(sses, 0);
                        foreach (SingleSteppingEngine sse in sses)
                        {
                            sse.ProcessEvent(status);
                        }
                        Dispose();
                        waiting = false;
                        return(true);
                    }
                    else
                    {
                        goto again;
                    }
                }

                if (engine == null)
                {
                    SingleSteppingEngine[] sses = new SingleSteppingEngine [thread_hash.Count];
                    thread_hash.Values.CopyTo(sses, 0);
                    Inferior inferior = sses[0].Inferior;
                    inferior.Process.ThreadCreated(inferior, pid, false, true);
                    goto again;
                }

                ArrayList check_threads = new ArrayList();
                bool      got_threads   = true;
                foreach (Process process in processes)
                {
                    got_threads = got_threads && process.CheckForThreads(check_threads);
                }

                if (got_threads)
                {
                    int[] lwps = new int [thread_hash.Count];
                    thread_hash.Keys.CopyTo(lwps, 0);
                    foreach (int lwp in lwps)
                    {
                        if (!check_threads.Contains(lwp))
                        {
                            SingleSteppingEngine old_engine = (SingleSteppingEngine)thread_hash [lwp];
                            thread_hash.Remove(old_engine.PID);
                            engine_hash.Remove(old_engine.ID);
                            old_engine.Process.OnThreadExitedEvent(old_engine);
                            old_engine.Dispose();
                        }
                    }
                }
            }

            SingleSteppingEngine event_engine = (SingleSteppingEngine)thread_hash [pid];

            if (event_engine == null && Inferior.HasThreadEvents)
            {
                int arg;
                Inferior.ChildEventType etype = mono_debugger_server_dispatch_simple(status, out arg);

                /*
                 * Ignore exit events from unknown children.
                 */

                if ((etype == Inferior.ChildEventType.CHILD_EXITED) && (arg == 0))
                {
                    goto again;
                }

                /*
                 * There is a race condition in the Linux kernel which shows up on >= 2.6.27:
                 *
                 * When creating a new thread, the initial stopping event of that thread is sometimes
                 * sent before sending the `PTRACE_EVENT_CLONE' for it.
                 *
                 * Because of this, we explicitly wait for the new thread to stop and ignore any
                 * "early" stopping signals.
                 *
                 * See also the comments in _server_ptrace_wait_for_new_thread() in x86-linux-ptrace.c
                 * and bugs #423518 and #466012.
                 *
                 */

                if ((etype != Inferior.ChildEventType.CHILD_STOPPED) || (arg != 0))
                {
                    Report.Error("WARNING: Got event {0:x} for unknown pid {1}", status, pid);
                    waiting = false;
                    RequestWait();
                    return(true);
                }

                if (!pending_sigstops.ContainsKey(pid))
                {
                    pending_sigstops.Add(pid, DateTime.Now);
                }

                Report.Debug(DebugFlags.Wait, "Ignoring SIGSTOP from unknown pid {0}.", pid);
                goto again;
            }

            engine_event.WaitOne();

            event_queue.Lock();
            engine_event.Reset();

            if (current_event != null)
            {
                Console.WriteLine("Current_event is not null: {0}", Environment.StackTrace);
                throw new InternalError();
            }

            current_event        = event_engine;
            current_event_status = status;

            waiting = false;

            event_queue.Signal();
            event_queue.Unlock();
            return(true);
        }
Beispiel #29
0
        // <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();
            }
        }
Beispiel #30
0
 internal void AddPendingEvent(SingleSteppingEngine engine, Inferior.ChildEvent cevent)
 {
     Report.Debug(DebugFlags.Wait, "Add pending event: {0} {1}", engine, cevent);
     pending_events.Add(engine, cevent);
 }
Beispiel #31
0
        internal bool HandleChildEvent(SingleSteppingEngine engine, Inferior inferior,
						ref Inferior.ChildEvent cevent, out bool resume_target)
        {
            if (cevent.Type == Inferior.ChildEventType.CHILD_NOTIFICATION) {
                NotificationType type = (NotificationType) cevent.Argument;

                Report.Debug (DebugFlags.EventLoop,
                          "{0} received notification {1}: {2}",
                          engine, type, cevent);

                switch (type) {
                case NotificationType.AcquireGlobalThreadLock:
                    Report.Debug (DebugFlags.Threads,
                              "{0} received notification {1}", engine, type);
                    engine.Process.AcquireGlobalThreadLock (engine);
                    break;

                case NotificationType.ReleaseGlobalThreadLock:
                    Report.Debug (DebugFlags.Threads,
                              "{0} received notification {1}", engine, type);
                    engine.Process.ReleaseGlobalThreadLock (engine);
                    break;

                case NotificationType.ThreadCreated: {
                    TargetAddress data = new TargetAddress (
                        inferior.AddressDomain, cevent.Data2);

                    TargetAddress lmf = inferior.ReadAddress (data + 8);
                    engine.SetManagedThreadData (lmf, data + 24);

                    if (MonoDebuggerInfo.CheckRuntimeVersion (81, 3)) {
                        int flags_offset = 56 + inferior.TargetAddressSize;
                        ThreadFlags flags = (ThreadFlags) inferior.ReadInteger (data + flags_offset);
                        check_thread_flags (engine, flags);
                    }

                    Report.Debug (DebugFlags.Threads,
                              "{0} managed thread created: {1:x} {2} {3} - {4}",
                              engine, cevent.Data1, data, lmf, engine.LMFAddress);
                    break;
                }

                case NotificationType.ThreadCleanup: {
                    TargetAddress data = new TargetAddress (
                        inferior.AddressDomain, cevent.Data1);

                    Report.Debug (DebugFlags.Threads,
                              "{0} managed thread cleanup: {1:x} {2}",
                              engine, cevent.Data2, data);
                    break;
                }

                case NotificationType.GcThreadCreated: {
                    TargetAddress data = new TargetAddress (
                        inferior.AddressDomain, cevent.Data1);
                    long tid = cevent.Data2;

                    Report.Debug (DebugFlags.Threads,
                              "{0} created gc thread: {1:x} {2}",
                              engine, tid, data);

                    engine = engine.Process.GetEngineByTID (inferior, tid);
                    if (engine == null)
                        throw new InternalError ();

                    engine.OnManagedThreadCreated (data);
                    break;
                }

                case NotificationType.GcThreadExited:
                    Report.Debug (DebugFlags.Threads, "{0} gc thread exited", engine);
                    engine.OnManagedThreadExited ();
                    try {
                        inferior.Continue ();
                    } catch {
                        // Ignore errors; for some reason, the thread may have died
                        // already by the time get this notification.
                    }
                    resume_target = false;
                    return true;

                case NotificationType.InitializeThreadManager:
                    csharp_language = inferior.Process.CreateMonoLanguage (
                        debugger_info);
                    if (engine.Process.IsAttached)
                        csharp_language.InitializeAttach (inferior);
                    else
                        csharp_language.Initialize (inferior);

                    break;

                case NotificationType.ReachedMain: {
                    Inferior.StackFrame iframe = inferior.GetCurrentFrame (false);
                    engine.SetMainReturnAddress (iframe.StackPointer);
                    engine.Process.OnProcessReachedMainEvent ();
                    resume_target = !engine.InitializeBreakpoints ();
                    return true;
                }

                case NotificationType.WrapperMain:
                    break;
                case NotificationType.MainExited:
                    engine.SetMainReturnAddress (TargetAddress.Null);
                    break;

                case NotificationType.UnhandledException:
                    cevent = new Inferior.ChildEvent (
                        Inferior.ChildEventType.UNHANDLED_EXCEPTION,
                        0, cevent.Data1, cevent.Data2);
                    resume_target = false;
                    return false;

                case NotificationType.HandleException:
                    cevent = new Inferior.ChildEvent (
                        Inferior.ChildEventType.HANDLE_EXCEPTION,
                        0, cevent.Data1, cevent.Data2);
                    resume_target = false;
                    return false;

                case NotificationType.ThrowException:
                    cevent = new Inferior.ChildEvent (
                        Inferior.ChildEventType.THROW_EXCEPTION,
                        0, cevent.Data1, cevent.Data2);
                    resume_target = false;
                    return false;

                case NotificationType.FinalizeManagedCode:
                    mono_debugger_server_finalize_mono_runtime (mono_runtime_info);
                    mono_runtime_info = IntPtr.Zero;
                    csharp_language = null;
                    break;

                case NotificationType.OldTrampoline:
                case NotificationType.Trampoline:
                    resume_target = false;
                    return false;

                case NotificationType.ClassInitialized:
                    break;

                case NotificationType.InterruptionRequest:
                    inferior.WriteInteger (MonoDebuggerInfo.InterruptionRequest, 0);
                    var callbacks = managed_callbacks;
                    managed_callbacks = new Queue<ManagedCallbackData> ();
                    resume_target = !engine.OnManagedCallback (callbacks);
                    return true;

                default: {
                    TargetAddress data = new TargetAddress (
                        inferior.AddressDomain, cevent.Data1);

                    resume_target = csharp_language.Notification (
                        engine, inferior, type, data, cevent.Data2);
                    return true;
                }
                }

                resume_target = true;
                return true;
            }

            if ((cevent.Type == Inferior.ChildEventType.CHILD_STOPPED) &&
                (cevent.Argument == thread_abort_signal)) {
                resume_target = true;
                return true;
            }

            if ((cevent.Type == Inferior.ChildEventType.CHILD_STOPPED) && (cevent.Argument != 0) && !
                engine.Process.Session.Config.StopOnManagedSignals) {
                if (inferior.IsManagedSignal ((int) cevent.Argument)) {
                    resume_target = true;
                    return true;
                }
            }

            resume_target = false;
            return false;
        }
Beispiel #32
0
 internal void ThreadCreated(SingleSteppingEngine sse)
 {
     sse.Inferior.SetRuntimeInfo (mono_runtime_info);
     if (!MonoDebuggerInfo.CheckRuntimeVersion (81, 3) && !process.IsAttached) {
         if (++index < 3)
             sse.Thread.ThreadFlags |= Thread.Flags.Daemon | Thread.Flags.Immutable;
     } else {
         sse.Thread.ThreadFlags |= Thread.Flags.Daemon | Thread.Flags.Immutable;
     }
 }
Beispiel #33
0
 void check_thread_flags(SingleSteppingEngine engine, ThreadFlags flags)
 {
     if ((flags & (ThreadFlags.Internal | ThreadFlags.ThreadPool)) != ThreadFlags.Internal) {
         engine.Thread.ThreadFlags &= ~(Thread.Flags.Daemon | Thread.Flags.Immutable);
         if (engine != process.MainThreadServant)
             process.Debugger.OnManagedThreadCreatedEvent (engine.Thread);
     } else if ((flags & ThreadFlags.ThreadPool) != 0) {
         engine.Thread.ThreadFlags &= ~Thread.Flags.Immutable;
     }
 }