Resubmit r354706 with a fix for process launch.

When the debugger is run in sync mode, you need to
be able to tell whether a hijacked resume is for some
special purpose (like waiting for the SIGSTOP on attach)
or just to perform a synchronous resume.  Target::Launch was doing
that wrong, and that caused stop-hooks on process launch
in source files to behave incorrectly.

<rdar://problem/48115661>

Differential Revision: https://reviews.llvm.org/D58727

llvm-svn: 355213
diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index f581f07..a60ec51 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -2554,12 +2554,14 @@
 
   StopHookCollection::iterator pos, end = m_stop_hooks.end();
 
-  // If there aren't any active stop hooks, don't bother either:
+  // If there aren't any active stop hooks, don't bother either.
+  // Also see if any of the active hooks want to auto-continue.
   bool any_active_hooks = false;
-  for (pos = m_stop_hooks.begin(); pos != end; pos++) {
-    if ((*pos).second->IsActive()) {
+  bool auto_continue = false;
+  for (auto hook : m_stop_hooks) {
+    if (hook.second->IsActive()) {
       any_active_hooks = true;
-      break;
+      auto_continue |= hook.second->GetAutoContinue();
     }
   }
   if (!any_active_hooks)
@@ -2595,6 +2597,7 @@
   bool hooks_ran = false;
   bool print_hook_header = (m_stop_hooks.size() != 1);
   bool print_thread_header = (num_exe_ctx != 1);
+  bool did_restart = false;
 
   for (pos = m_stop_hooks.begin(); keep_going && pos != end; pos++) {
     // result.Clear();
@@ -2639,10 +2642,13 @@
         options.SetPrintResults(true);
         options.SetAddToHistory(false);
 
+        // Force Async:
+        bool old_async = GetDebugger().GetAsyncExecution();
+        GetDebugger().SetAsyncExecution(true);
         GetDebugger().GetCommandInterpreter().HandleCommands(
             cur_hook_sp->GetCommands(), &exc_ctx_with_reasons[i], options,
             result);
-
+        GetDebugger().SetAsyncExecution(old_async);
         // If the command started the target going again, we should bag out of
         // running the stop hooks.
         if ((result.GetStatus() == eReturnStatusSuccessContinuingNoResult) ||
@@ -2651,13 +2657,19 @@
           StopHookCollection::iterator tmp = pos;
           if (++tmp != end)
             result.AppendMessageWithFormat("\nAborting stop hooks, hook %" PRIu64
-                                           " set the program running.\n",
+                                           " set the program running.\n"
+                                           "  Consider using '-G true' to make "
+                                           "stop hooks auto-continue.\n",
                                            cur_hook_sp->GetID());
           keep_going = false;
+          did_restart = true;
         }
       }
     }
   }
+  // Finally, if auto-continue was requested, do it now:
+  if (!did_restart && auto_continue)
+    m_process_sp->PrivateResume();
 
   result.GetImmediateOutputStream()->Flush();
   result.GetImmediateErrorStream()->Flush();
@@ -2914,17 +2926,11 @@
       if (state == eStateStopped) {
         if (!launch_info.GetFlags().Test(eLaunchFlagStopAtEntry)) {
           if (synchronous_execution) {
-            error = m_process_sp->PrivateResume();
-            if (error.Success()) {
-              state = m_process_sp->WaitForProcessToStop(
-                  llvm::None, nullptr, true, hijack_listener_sp, stream);
-              const bool must_be_alive =
-                  false; // eStateExited is ok, so this must be false
-              if (!StateIsStoppedState(state, must_be_alive)) {
-                error.SetErrorStringWithFormat("process isn't stopped: %s",
-                                               StateAsCString(state));
-              }
-            }
+            // Now we have handled the stop-from-attach, and we are just switching
+            // to a synchronous resume.  So we should switch to the SyncResume
+            // hijacker.
+            m_process_sp->RestoreProcessEvents();
+            m_process_sp->ResumeSynchronous(stream);
           } else {
             m_process_sp->RestoreProcessEvents();
             error = m_process_sp->PrivateResume();
@@ -3143,12 +3149,13 @@
 //--------------------------------------------------------------
 Target::StopHook::StopHook(lldb::TargetSP target_sp, lldb::user_id_t uid)
     : UserID(uid), m_target_sp(target_sp), m_commands(), m_specifier_sp(),
-      m_thread_spec_up(), m_active(true) {}
+      m_thread_spec_up() {}
 
 Target::StopHook::StopHook(const StopHook &rhs)
     : UserID(rhs.GetID()), m_target_sp(rhs.m_target_sp),
       m_commands(rhs.m_commands), m_specifier_sp(rhs.m_specifier_sp),
-      m_thread_spec_up(), m_active(rhs.m_active) {
+      m_thread_spec_up(), m_active(rhs.m_active),
+      m_auto_continue(rhs.m_auto_continue) {
   if (rhs.m_thread_spec_up)
     m_thread_spec_up.reset(new ThreadSpec(*rhs.m_thread_spec_up));
 }
@@ -3175,6 +3182,9 @@
   else
     s->Indent("State: disabled\n");
 
+  if (m_auto_continue)
+    s->Indent("AutoContinue on\n");
+
   if (m_specifier_sp) {
     s->Indent();
     s->PutCString("Specifier:\n");