Improve evalwaiter eval abort logic.
authorMikhail Kurinnoi <m.kurinnoi@samsung.com>
Tue, 11 Apr 2023 09:22:03 +0000 (12:22 +0300)
committerGleb Balykov/Advanced System SW Lab /SRR/Staff Engineer/Samsung Electronics <g.balykov@samsung.com>
Tue, 25 Apr 2023 18:28:08 +0000 (21:28 +0300)
In case timeout happens, will provide proper error code even if eval was completed (same as MS vsdbg do), will not hangs debugger in case abort failed and eval freeze (so, user could close debugger now).

src/debugger/evalstackmachine.cpp
src/debugger/evalwaiter.cpp

index d0d0e965c66feb7a2817a18084d260ac0459c28e..7863dec04c21ea8ca09774d445b5215ddbd98535 100644 (file)
@@ -2032,6 +2032,9 @@ HRESULT EvalStackMachine::Run(ICorDebugThread *pThread, FrameLevel frameLevel, i
         case CORDBG_E_CANT_CALL_ON_THIS_THREAD:
             output = "The function evaluation requires all threads to run.";
             break;
+        case E_UNEXPECTED:
+            output = "Evaluation timed out, but function evaluation can't be completed or aborted. Debuggee have inconsistent state now.";
+            break;
         default:
             break;
     }
index 0260bdb953c2d85fdc63d7a7a4f56738156f8f54..e0c9e73e38df2bef6ab5b0d6cf4e20ed828c8ab7 100644 (file)
@@ -142,6 +142,7 @@ HRESULT EvalWaiter::WaitEvalResult(ICorDebugThread *pThread,
         }\r
     };\r
 \r
+    bool evalTimeOut = false;\r
     auto WaitResult = [&]() -> HRESULT\r
     {\r
         ChangeThreadsState(THREAD_SUSPEND);\r
@@ -187,8 +188,19 @@ HRESULT EvalWaiter::WaitEvalResult(ICorDebugThread *pThread,
                         iCorEval2->RudeAbort();\r
                 }\r
 \r
+                evalTimeOut = true;\r
                 iCorProcess->Continue(0);\r
             }\r
+            // Wait for 5 more seconds, give `Abort()` a chance.\r
+            timeoutStatus = f.wait_for(std::chrono::milliseconds(5000));\r
+            if (timeoutStatus == std::future_status::timeout)\r
+            {\r
+                // Looks like can't be aborted, this is fatal error for debugger (debuggee have inconsistent state now).\r
+                iCorProcess->Stop(0);\r
+                m_evalResult.reset(nullptr);\r
+                LOGE("Fatal error, eval abort failed.");\r
+                return E_UNEXPECTED;\r
+            }\r
 \r
             auto evalResult = f.get();\r
             IfFailRet(evalResult.get()->Status);\r
@@ -216,6 +228,11 @@ HRESULT EvalWaiter::WaitEvalResult(ICorDebugThread *pThread,
         else\r
             ret = m_evalCanceled ? COR_E_OPERATIONCANCELED : COR_E_TIMEOUT;\r
     }\r
+    // In this case we have same behaviour as MS vsdbg and MSVS C# debugger - in case it was aborted with timeout, show proper error.\r
+    else if (evalTimeOut)\r
+    {\r
+        ret = (ret == E_UNEXPECTED) ? E_UNEXPECTED : COR_E_TIMEOUT;\r
+    }\r
 \r
     ChangeThreadsState(THREAD_RUN);\r
     return ret;\r