Fix exception behaviour in implicit function execution during eval.
authorMikhail Kurinnoi <m.kurinnoi@samsung.com>
Mon, 18 May 2020 16:19:26 +0000 (19:19 +0300)
committer이형주/Common Platform Lab(SR)/Staff Engineer/삼성전자 <leee.lee@samsung.com>
Thu, 21 May 2020 21:27:05 +0000 (06:27 +0900)
src/debug/netcoredbg/manageddebugger.cpp

index e100cbe94f37736dd1d74d75d487f00d42e6dbf4..727ea6a38adc84330b2db2c8958c1b1dd2e5ea89 100644 (file)
@@ -501,12 +501,44 @@ public:
         {
             LogFuncEntry();
 
+            HRESULT Status = S_OK;
+
             // TODO: Need implementation
             //
             // This is callback EvalException invoked on evaluation interruption event.
             // And, evaluated results has inconsistent states. Notify is not enough for this point.
 
             m_debugger.m_evaluator.NotifyEvalComplete(pThread, pEval);
+
+            // NOTE
+            // In case of unhandled exception inside implicit function call (for example, getter),
+            // ICorDebugManagedCallback::EvalException() is exit point for eval routine, make sure,
+            // that proper threads states are setted up.
+            if (m_debugger.m_evaluator.is_empty_eval_queue())
+            {
+                pAppDomain->SetAllThreadsDebugState(THREAD_RUN, nullptr);
+            }
+            else
+            {
+                DWORD currentThreadId;
+                pThread->GetID(&currentThreadId);
+                DWORD evalThreadId = m_debugger.m_evaluator.front_eval_queue();
+                if (evalThreadId == currentThreadId) {
+                    m_debugger.m_evaluator.pop_eval_queue();
+
+                    DWORD evalThreadId = m_debugger.m_evaluator.front_eval_queue();
+                    ToRelease<ICorDebugThread> pThreadEval;
+                    IfFailRet(m_debugger.m_pProcess->GetThread(evalThreadId, &pThreadEval));
+                    IfFailRet(pAppDomain->SetAllThreadsDebugState(THREAD_SUSPEND, nullptr));
+                    IfFailRet(pThreadEval->SetDebugState(THREAD_RUN));
+
+                    Logger::levelLog(LOG_INFO, "Eval exception, threadid = '%d'", currentThreadId);
+                }
+                else {
+                    Logger::levelLog(LOG_ERROR, "Logical error: eval queue '%d' != '%d'", currentThreadId, evalThreadId);
+                }
+            }
+
             return S_OK;
         }
 
@@ -778,6 +810,14 @@ public:
         {
             LogFuncEntry();
 
+            // In case we inside evaluation (exception during implicit function execution), make sure we continue process execution.
+            // This is internal CoreCLR routine, should not be interrupted by debugger. CoreCLR will care about exception in this case
+            // and provide exception data as evaluation result in case of unhandled exception.
+            if (m_debugger.m_evaluator.IsEvalRunning() && m_debugger.m_evaluator.FindEvalForThread(pThread))
+            {
+                return pAppDomain->Continue(0);
+            }
+
             // INFO: Exception event callbacks produce Stop process and managed threads in coreCLR
             // After emit Stop event from debugger coreclr by command handler send a ExceptionInfo request.
             // For answer on ExceptionInfo are needed long FuncEval() with asynchronous EvalComplete event.