Mono.Debugger.Backend.ThreadManager.wait_thread_main C# (CSharp) Method

wait_thread_main() private method

private wait_thread_main ( ) : bool
return bool
        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;
        }