Suppress calling finalizer for incomplete object
authorKonstantin Baladurin <k.baladurin@partner.samsung.com>
Thu, 9 Aug 2018 16:25:30 +0000 (19:25 +0300)
committerKonstantin Baladurin <k.baladurin@partner.samsung.com>
Thu, 9 Aug 2018 16:25:30 +0000 (19:25 +0300)
Finalize shouldn't be called for objects that aren't initialized
by ctor.

src/debug/netcoredbg/expr.cpp
src/debug/netcoredbg/manageddebugger.h
src/debug/netcoredbg/valuewalk.cpp

index 52c0422..4788544 100644 (file)
@@ -144,7 +144,7 @@ static HRESULT GetMethodToken(IMetaDataImport *pMD, mdTypeDef cl, const WCHAR *m
     return methodDef;
 }
 
-static HRESULT FindFunction(ICorDebugModule *pModule,
+HRESULT Evaluator::FindFunction(ICorDebugModule *pModule,
                             const WCHAR *typeName,
                             const WCHAR *methodName,
                             ICorDebugFunction **ppFunction)
index 68895e6..e1b0610 100644 (file)
@@ -34,6 +34,7 @@ private:
 
     ToRelease<ICorDebugFunction> m_pRunClassConstructor;
     ToRelease<ICorDebugFunction> m_pGetTypeHandle;
+    ToRelease<ICorDebugFunction> m_pSuppressFinalize;
 
     std::mutex m_evalMutex;
     std::unordered_map< DWORD, std::promise< std::unique_ptr<ToRelease<ICorDebugValue>> > > m_evalResults;
@@ -64,7 +65,8 @@ private:
     HRESULT EvalObjectNoConstructor(
         ICorDebugThread *pThread,
         ICorDebugType *pType,
-        ICorDebugValue **ppEvalResult);
+        ICorDebugValue **ppEvalResult,
+        bool suppressFinalize = true);
 
     std::future< std::unique_ptr<ToRelease<ICorDebugValue>> > RunEval(
         ICorDebugThread *pThread,
@@ -113,6 +115,13 @@ private:
         ICorDebugThread *pThread,
         std::vector< ToRelease<ICorDebugType> > &types);
 
+
+    static HRESULT FindFunction(
+        ICorDebugModule *pModule,
+        const WCHAR *typeName,
+        const WCHAR *methodName,
+        ICorDebugFunction **ppFunction);
+
 public:
 
     Evaluator(Modules &modules) : m_modules(modules) {}
index f88ccf6..cd96322 100644 (file)
@@ -82,6 +82,9 @@ HRESULT Evaluator::WaitEvalResult(ICorDebugThread *pThread,
     try
     {
         auto evalResult = RunEval(pThread, pEval).get();
+        if (!ppEvalResult)
+            return S_OK;
+
         if (!evalResult->GetPtr())
             return E_FAIL;
         *ppEvalResult = evalResult->Detach();
@@ -139,7 +142,8 @@ HRESULT Evaluator::EvalFunction(
 HRESULT Evaluator::EvalObjectNoConstructor(
     ICorDebugThread *pThread,
     ICorDebugType *pType,
-    ICorDebugValue **ppEvalResult)
+    ICorDebugValue **ppEvalResult,
+    bool suppressFinalize)
 {
     HRESULT Status = S_OK;
 
@@ -172,7 +176,27 @@ HRESULT Evaluator::EvalObjectNoConstructor(
         (ICorDebugType **)typeParams.data()
     ));
 
-    return WaitEvalResult(pThread, pEval, ppEvalResult);
+    IfFailRet(WaitEvalResult(pThread, pEval, ppEvalResult));
+
+    if (suppressFinalize)
+    {
+        if (!m_pSuppressFinalize)
+        {
+            ToRelease<ICorDebugModule> pModule;
+            IfFailRet(m_modules.GetModuleWithName("System.Private.CoreLib.dll", &pModule));
+
+            static const WCHAR gcName[] = W("System.GC");
+            static const WCHAR suppressFinalizeMethodName[] = W("SuppressFinalize");
+            IfFailRet(FindFunction(pModule, gcName, suppressFinalizeMethodName, &m_pSuppressFinalize));
+        }
+
+        if (!m_pSuppressFinalize)
+            return E_FAIL;
+
+        IfFailRet(EvalFunction(pThread, m_pSuppressFinalize, nullptr, *ppEvalResult, nullptr /* void method */));
+    }
+
+    return S_OK;
 }
 
 static HRESULT FindMethod(ICorDebugType *pType, WCHAR *methodName, ICorDebugFunction **ppFunc)