Fix Break All behavior in Visual Studio
authorIgor Kulaychuk <i.kulaychuk@samsung.com>
Fri, 4 May 2018 11:50:57 +0000 (14:50 +0300)
committerIgor Kulaychuk <i.kulaychuk@samsung.com>
Thu, 10 May 2018 00:13:01 +0000 (09:13 +0900)
src/debug/netcoredbg/manageddebugger.cpp
src/debug/netcoredbg/miprotocol.cpp

index cc540f8..6652cc9 100644 (file)
@@ -796,8 +796,50 @@ HRESULT ManagedDebugger::Pause()
     if (!m_pProcess)
         return E_FAIL;
     HRESULT Status = m_pProcess->Stop(0);
-    if (Status == S_OK)
-        m_protocol->EmitStoppedEvent(StoppedEvent(StopPause, 0));
+    if (Status != S_OK)
+        return Status;
+
+    // For Visual Studio, we have to report a thread ID in async stop event.
+    // We have to find a thread which has a stack frame with valid location in its stack trace.
+    std::vector<Thread> threads;
+    GetThreads(threads);
+
+    int lastStoppedId = GetLastStoppedThreadId();
+
+    // Reorder threads so that last stopped thread is checked first
+    for (size_t i = 0; i < threads.size(); ++i)
+    {
+        if (threads[i].id == lastStoppedId)
+        {
+            std::swap(threads[0], threads[i]);
+            break;
+        }
+    }
+
+    // Now get stack trace for each thread and find a frame with valid source location.
+    for (const Thread& thread : threads)
+    {
+        int totalFrames = 0;
+        std::vector<StackFrame> stackFrames;
+
+        if (FAILED(GetStackTrace(thread.id, 0, 0, stackFrames, totalFrames)))
+            continue;
+
+        for (const StackFrame& stackFrame : stackFrames)
+        {
+            if (stackFrame.source.IsNull())
+                continue;
+
+            StoppedEvent event(StopPause, thread.id);
+            event.frame = stackFrame;
+            m_protocol->EmitStoppedEvent(event);
+
+            return Status;
+        }
+    }
+
+    m_protocol->EmitStoppedEvent(StoppedEvent(StopPause, 0));
+
     return Status;
 }
 
index 8c8a9fc..4907bad 100644 (file)
@@ -471,7 +471,10 @@ void MIProtocol::EmitStoppedEvent(StoppedEvent event)
         }
         case StopPause:
         {
-            MIProtocol::Printf("*stopped,reason=\"interrupted\",stopped-threads=\"all\"\n");
+            // When async break happens, this should be reason="interrupted".
+            // But MIEngine in Visual Studio accepts only reason="signal-received",signal-name="SIGINT".
+            MIProtocol::Printf("*stopped,reason=\"signal-received\",signal-name=\"SIGINT\",thread-id=\"%i\",stopped-threads=\"all\",frame={%s}\n",
+                event.threadId, frameLocation.c_str());
             return;
         }
         case StopEntry: