BUG#:8417 RELEASE_2_7_3-RC1
authormarek <marek>
Tue, 9 Jun 2009 09:19:40 +0000 (09:19 +0000)
committermarek <marek>
Tue, 9 Jun 2009 09:19:40 +0000 (09:19 +0000)
TITLE: C++ CMPI BaseMI does not handle CIM Server shutdown

DESCRIPTION:

src/Pegasus/Provider/CMPI/CmpiBaseMI.h
src/Pegasus/Provider/CMPI/CmpiImpl.cpp
src/Pegasus/ProviderManager2/CMPI/CMPIProvider.cpp

index fd1ad6b529d854d89adc254e97de29af27645ddc..0a3a5bb284e94883947d87c588cc7db309853921 100644 (file)
@@ -60,7 +60,7 @@ public:
     static CMPIStatus driveBaseCleanup(
         void* mi,
         const CMPIContext* eCtx,
-        CMPIBoolean b);
+        CMPIBoolean terminating);
 
     virtual CmpiStatus initialize(const CmpiContext& ctx);
     virtual CmpiStatus cleanup(CmpiContext& ctx);
index fb55b26f6213fb920630452821ebbbfa640f80a5..d3e684f3de9a00e89a1865c321f107805d5d9001 100644 (file)
@@ -74,7 +74,7 @@ CmpiBaseMI::~CmpiBaseMI()
 CMPIStatus CmpiBaseMI::driveBaseCleanup(
     void* vi,
     const CMPIContext* eCtx,
-    CMPIBoolean b)
+    CMPIBoolean terminating)
 {
     try
     {
@@ -82,20 +82,63 @@ CMPIStatus CmpiBaseMI::driveBaseCleanup(
         CmpiContext ctx((CMPIContext*)eCtx);
         CmpiStatus rc(CMPI_RC_OK);
         CmpiBaseMI* cmi = reinterpret_cast<CmpiBaseMI*>(mi->hdl);
-        if (cmi->isUnloadable())
+        if (!terminating)
         {
-            if (cmi->getProviderBase() && 
-                cmi->getProviderBase()->decUseCount()==0)
+            if (cmi->isUnloadable())
             {
-                cmi->getProviderBase()->setBaseMI(0);
-                cmi->setProviderBase(0);
-                rc=cmi->cleanup(ctx);
-                delete cmi;
+                if (cmi->getProviderBase() &&
+                    cmi->getProviderBase()->decUseCount()==0)
+                {
+                    rc=cmi->cleanup(ctx);
+                    if (rc.rc() == CMPI_RC_OK)
+                    {
+                        cmi->getProviderBase()->setBaseMI(0);
+                        cmi->setProviderBase(0);
+                        delete cmi;
+                    }
+                    else
+                    {
+                        /* some error occured, do NOT delete the MI 
+                           increase MI count again
+                        */
+                        cmi->getProviderBase()->incUseCount();
+                    }
+                }
+            }
+            else
+            {
+                rc = CmpiStatus(CMPI_RC_ERR_NOT_SUPPORTED);
             }
         }
         else
         {
-            rc = CmpiStatus(CMPI_RC_ERR_NOT_SUPPORTED);
+            if (cmi->getProviderBase() &&
+                cmi->getProviderBase()->decUseCount()==0)
+            {
+                rc=cmi->cleanup(ctx);
+                /* the CMPI 2.0 spec says that cleanup function can return 
+                   the following errors:
+                   CMPI_RC_OK - Operation successful.
+                   CMPI_RC_ERR_FAILED - Unspecific error occurred.
+                   CMPI_RC_DO_NOT_UNLOAD and CMPI_RC_NEVER_UNLOAD - need to be
+                   ignored in the terminating case, CIM server is going down
+                   anyway
+                */                   
+                if (rc.rc() != CMPI_RC_ERR_FAILED)
+                {
+                    cmi->getProviderBase()->setBaseMI(0);
+                    cmi->setProviderBase(0);
+                    delete cmi;
+                    rc = CmpiStatus(CMPI_RC_OK);
+                }
+                else
+                {
+                    /* give the provider some grace on shutdown,
+                    the MI will not be cleaned up in this case, but as the CIM
+                    Server is shutting down anyway, that does not hurt */
+                    cmi->getProviderBase()->incUseCount();
+                }
+            }
         }
         return rc.status();
     }
index eb1f68e601b8c6f72989054ccfbeefdf1e28389f..0072e145e78f9e8f3e5c39c17bcae16ea2467e23 100644 (file)
@@ -396,6 +396,12 @@ void CMPIProvider::_terminate(Boolean terminating)
         // Wait until all of the threads have been cleaned.
         waitUntilThreadsDone();
     }
+    // We have killed all threads running in provider forcibly. Set 
+    // unloadStatus of provider to OK.
+    if (terminating)
+    {
+        unloadStatus = CMPI_RC_OK;
+    }
     PEG_METHOD_EXIT();
 }
 
@@ -412,12 +418,7 @@ void CMPIProvider::terminate()
         {
 
             _terminate(true);
-            if (unloadStatus != CMPI_RC_OK)
-            {
-                _status=savedStatus;
-                PEG_METHOD_EXIT();
-                return;
-            }
+            PEGASUS_ASSERT(unloadStatus == CMPI_RC_OK);
         }
         catch (...)
         {