[IOT-3286] IoTivity may hang on exit 53/29553/6
authorIurii Metelytsia <i.metelytsia@samsung.com>
Thu, 13 Jun 2019 11:10:39 +0000 (14:10 +0300)
committerNathan Heldt-Sheller <nathan.heldt-sheller@intel.com>
Thu, 18 Jul 2019 17:01:59 +0000 (17:01 +0000)
1. Reference counter has been added to ssl adapter.
2. Waiting for ReceiveThread when the caipserver is stopped added.

Signed-off-by: Iurii Metelytsia <i.metelytsia@samsung.com>
Change-Id: I3ccf95ff1c851fe0d3e70f75ed00fdb1fce7bf82

resource/csdk/connectivity/inc/ca_adapter_net_ssl.h
resource/csdk/connectivity/src/adapter_util/ca_adapter_net_ssl.c
resource/csdk/connectivity/src/bt_le_adapter/caleadapter.c
resource/csdk/connectivity/src/ip_adapter/caipadapter.c
resource/csdk/connectivity/src/ip_adapter/caipserver.c
resource/csdk/connectivity/src/tcp_adapter/catcpadapter.c
resource/csdk/connectivity/test/ssladapter_test.cpp

index 140aac1..081e704 100644 (file)
@@ -111,8 +111,17 @@ CAResult_t CAinitSslAdapter(void);
 
 /**
  * de-inits mbedTLS library and free the allocated memory.
+ *
+ * @param[in]  cleanup  perform cleanup of allocated memory.
+ *             If this flag is false, need to perform cleanup
+ *             by calling CAcleanupSslAdapter.
+ */
+void CAdeinitSslAdapter(bool cleanup);
+
+/**
+ * Free allocated memory
  */
-void CAdeinitSslAdapter(void);
+void CAcleanupSslAdapter(void);
 
 /**
  * Performs TLS encryption of the CoAP PDU.
index dede14f..252220f 100644 (file)
@@ -431,6 +431,12 @@ static CAcloseSslConnectionCallback g_closeSslConnectionCallback = NULL;
  */
 static oc_mutex g_sslContextMutex = NULL;
 
+/**
+ * @var g_sslInterestedThreadsCount
+ * @brief The number of threads that use this module
+ */
+static int g_sslInterestedThreadsCount = 0;
+
 /**
  * @var g_sslCallback
  * @brief callback to deliver the TLS handshake result
@@ -1717,7 +1723,7 @@ static void StopRetransmit(void)
     }
 }
 #endif
-void CAdeinitSslAdapter(void)
+void CAdeinitSslAdapter(bool cleanup)
 {
     OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
 
@@ -1753,8 +1759,34 @@ void CAdeinitSslAdapter(void)
 
     // Unlock tlsContext mutex and de-initialize it
     oc_mutex_unlock(g_sslContextMutex);
-    oc_mutex_free(g_sslContextMutex);
-    g_sslContextMutex = NULL;
+
+    if (cleanup)
+    {
+        CAcleanupSslAdapter();
+    }
+
+    OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s ", __func__);
+}
+
+void CAcleanupSslAdapter(void)
+{
+    bool free_mutex = false;
+
+    OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
+
+    VERIFY_NON_NULL_VOID(g_sslContextMutex, NET_SSL_TAG, "context mutex is NULL");
+
+    oc_mutex_lock(g_sslContextMutex);
+    if (g_sslInterestedThreadsCount > 0 && --g_sslInterestedThreadsCount == 0)
+    {
+        free_mutex = true;
+    }
+    oc_mutex_unlock(g_sslContextMutex);
+    if (free_mutex)
+    {
+        oc_mutex_free(g_sslContextMutex);
+        g_sslContextMutex = NULL;
+    }
 
     OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s ", __func__);
 }
@@ -1868,17 +1900,27 @@ CAResult_t CAinitSslAdapter(void)
         g_sslContextMutex = oc_mutex_new_recursive();
         VERIFY_NON_NULL_RET(g_sslContextMutex, NET_SSL_TAG, "oc_mutex_new_recursive failed",
             CA_MEMORY_ALLOC_FAILED);
+
+        oc_mutex_lock(g_sslContextMutex);
+        g_sslInterestedThreadsCount = 0;
     }
     else
     {
         OIC_LOG(INFO, NET_SSL_TAG, "Done already!");
-        return CA_STATUS_OK;
+
+        oc_mutex_lock(g_sslContextMutex);
+        if (NULL != g_caSslContext)
+        {
+            g_sslInterestedThreadsCount++;
+            oc_mutex_unlock(g_sslContextMutex);
+            return CA_STATUS_OK;
+        }
     }
 
     // Lock tlsContext mutex and create tlsContext
-    oc_mutex_lock(g_sslContextMutex);
-    g_caSslContext = (SslContext_t *)OICCalloc(1, sizeof(SslContext_t));
+    g_sslInterestedThreadsCount++;
 
+    g_caSslContext = (SslContext_t *)OICCalloc(1, sizeof(SslContext_t));
     if (NULL == g_caSslContext)
     {
         OIC_LOG(ERROR, NET_SSL_TAG, "Context malloc failed");
@@ -1925,7 +1967,7 @@ CAResult_t CAinitSslAdapter(void)
     {
         OIC_LOG(ERROR, NET_SSL_TAG, "Seed initialization failed!");
         oc_mutex_unlock(g_sslContextMutex);
-        CAdeinitSslAdapter();
+        CAdeinitSslAdapter(true);
         return CA_STATUS_FAILED;
     }
     mbedtls_ctr_drbg_set_prediction_resistance(&g_caSslContext->rnd, MBEDTLS_CTR_DRBG_PR_ON);
@@ -1936,7 +1978,7 @@ CAResult_t CAinitSslAdapter(void)
     {
         OIC_LOG(ERROR, NET_SSL_TAG, "Client config initialization failed!");
         oc_mutex_unlock(g_sslContextMutex);
-        CAdeinitSslAdapter();
+        CAdeinitSslAdapter(true);
         OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
         return CA_STATUS_FAILED;
     }
@@ -1946,7 +1988,7 @@ CAResult_t CAinitSslAdapter(void)
     {
         OIC_LOG(ERROR, NET_SSL_TAG, "Server config initialization failed!");
         oc_mutex_unlock(g_sslContextMutex);
-        CAdeinitSslAdapter();
+        CAdeinitSslAdapter(true);
         OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
         return CA_STATUS_FAILED;
     }
@@ -1958,7 +2000,7 @@ CAResult_t CAinitSslAdapter(void)
     {
         OIC_LOG(ERROR, NET_SSL_TAG, "Cookie setup failed!");
         oc_mutex_unlock(g_sslContextMutex);
-        CAdeinitSslAdapter();
+        CAdeinitSslAdapter(true);
         OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
         return CA_STATUS_FAILED;
     }
@@ -1968,7 +2010,7 @@ CAResult_t CAinitSslAdapter(void)
     {
         OIC_LOG(ERROR, NET_SSL_TAG, "Client config initialization failed!");
         oc_mutex_unlock(g_sslContextMutex);
-        CAdeinitSslAdapter();
+        CAdeinitSslAdapter(true);
         OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
         return CA_STATUS_FAILED;
     }
@@ -1978,7 +2020,7 @@ CAResult_t CAinitSslAdapter(void)
     {
         OIC_LOG(ERROR, NET_SSL_TAG, "Server config initialization failed!");
         oc_mutex_unlock(g_sslContextMutex);
-        CAdeinitSslAdapter();
+        CAdeinitSslAdapter(true);
         OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
         return CA_STATUS_FAILED;
     }
index 9345e7b..c9e4768 100644 (file)
@@ -2658,7 +2658,7 @@ static CAResult_t CAStartLE(void)
 static CAResult_t CAStopLE(void)
 {
 #ifdef __WITH_DTLS__
-    CAdeinitSslAdapter();
+    CAdeinitSslAdapter(false);
 #endif
 
     CAStopLEQueues();
@@ -2680,6 +2680,11 @@ static CAResult_t CAStopLE(void)
             break;
     }
     oc_mutex_unlock(g_bleIsServerMutex);
+
+#ifdef __WITH_DTLS__
+    CAcleanupSslAdapter();
+#endif
+
     return CAStopLEAdapter();
 }
 
index eeef303..a226bd0 100644 (file)
@@ -550,7 +550,7 @@ CAResult_t CAReadIPData(void)
 CAResult_t CAStopIP(void)
 {
 #ifdef __WITH_DTLS__
-    CAdeinitSslAdapter();
+    CAdeinitSslAdapter(false);
 #endif
 
     if (g_sendQueueHandle && g_sendQueueHandle->threadMutex)
@@ -561,6 +561,10 @@ CAResult_t CAStopIP(void)
     CAIPStopNetworkMonitor(CA_ADAPTER_IP);
     CAIPStopServer();
 
+#ifdef __WITH_DTLS__
+    CAcleanupSslAdapter();
+#endif
+
     return CA_STATUS_OK;
 }
 
index f386a1f..024505f 100644 (file)
@@ -153,6 +153,13 @@ static CAIPErrorHandleCallback g_ipErrorHandler = NULL;
 
 static CAIPPacketReceivedCallback g_packetReceivedCallback = NULL;
 
+static oc_mutex g_mutex = NULL;
+static oc_cond g_condVar = NULL;
+
+static CAResult_t CAIPCreateMutex(void);
+static void CAIPDestroyMutex(void);
+static CAResult_t CAIPCreateCond(void);
+static void CAIPDestroyCond(void);
 static void CAFindReadyMessage(void);
 #if !defined(WSA_WAIT_EVENT_0)
 static void CASelectReturned(fd_set *readFds, int ret);
@@ -162,6 +169,47 @@ static void CAEventReturned(CASocketFd_t socket);
 
 static CAResult_t CAReceiveMessage(CASocketFd_t fd, CATransportFlags_t flags);
 
+static CAResult_t CAIPCreateMutex(void)
+{
+    if (!g_mutex)
+    {
+        if (NULL == (g_mutex = oc_mutex_new()))
+        {
+            OIC_LOG(ERROR, TAG, "Failed to created mutex!");
+            return CA_STATUS_FAILED;
+        }
+    }
+    return CA_STATUS_OK;
+}
+static void CAIPDestroyMutex(void)
+{
+    if (g_mutex)
+    {
+        oc_mutex_free(g_mutex);
+        g_mutex = NULL;
+    }
+}
+static CAResult_t CAIPCreateCond(void)
+{
+    if (!g_condVar)
+    {
+        if (NULL == (g_condVar = oc_cond_new()))
+        {
+            OIC_LOG(ERROR, TAG, "Failed to created cond!");
+            return CA_STATUS_FAILED;
+        }
+    }
+    return CA_STATUS_OK;
+}
+static void CAIPDestroyCond(void)
+{
+    if (g_condVar)
+    {
+        oc_cond_free(g_condVar);
+        g_condVar = NULL;
+    }
+}
+
 static void CACloseFDs(void)
 {
 #if !defined(WSA_WAIT_EVENT_0)
@@ -183,6 +231,10 @@ static void CAReceiveHandler(void *data)
         CAFindReadyMessage();
     }
     CACloseFDs();
+
+    oc_mutex_lock(g_mutex);
+    oc_cond_signal(g_condVar);
+    oc_mutex_unlock(g_mutex);
 }
 
 #define CLOSE_SOCKET(TYPE) \
@@ -1001,6 +1053,18 @@ CAResult_t CAIPStartServer(const ca_thread_pool_t threadPool)
         return CA_STATUS_FAILED;
     }
 #endif
+
+    res = CAIPCreateMutex();
+    if (CA_STATUS_OK == res)
+    {
+        res = CAIPCreateCond();
+    }
+    if (CA_STATUS_OK != res)
+    {
+        OIC_LOG(ERROR, TAG, "failed to create mutex/cond");
+        return res;
+    }
+
     // set up appropriate FD mechanism for fast shutdown
     CAInitializeFastShutdownMechanism();
 
@@ -1033,6 +1097,20 @@ void CAIPStopServer(void)
 {
     caglobals.ip.terminate = true;
 
+    if (!caglobals.ip.started)
+    {
+        // Close fd's since receive handler was not started
+        CACloseFDs();
+    }
+    else
+    {
+        caglobals.ip.started = false;
+        // wait for thread finished
+        oc_mutex_lock(g_mutex);
+        oc_cond_wait_for(g_condVar, g_mutex, 300000);
+        oc_mutex_unlock(g_mutex);
+    }
+
 #if !defined(WSA_WAIT_EVENT_0)
     if (caglobals.ip.shutdownFds[1] != -1)
     {
@@ -1052,11 +1130,8 @@ void CAIPStopServer(void)
     }
 #endif
 
-    if (!caglobals.ip.started)
-    { // Close fd's since receive handler was not started
-        CACloseFDs();
-    }
-    caglobals.ip.started = false;
+    CAIPDestroyMutex();
+    CAIPDestroyCond();
 }
 
 void CAWakeUpForChange(void)
index 675da5a..4beacbb 100644 (file)
@@ -547,7 +547,7 @@ CAResult_t CAStopTCP()
     CAInitializeTCPGlobals();
 
 #ifdef __WITH_TLS__
-    CAdeinitSslAdapter();
+    CAdeinitSslAdapter(true);
 #endif
 
     return CA_STATUS_OK;
index 029574e..f7d0729 100644 (file)
@@ -50,6 +50,7 @@
 #define GetCASecureEndpointAttributes GetCASecureEndpointAttributesTest
 #define CAsetPeerCNVerifyCallback CAsetPeerCNVerifyCallbackTest
 #define CAsetCloseSslConnectionCallback CAsetCloseSslConnectionCallbackTest
+#define CAcleanupSslAdapter CAcleanupSslAdapterTest
 
 #include "../src/adapter_util/ca_adapter_net_ssl.c"
 
@@ -1891,7 +1892,7 @@ static int testCAinitSslAdapter()
     result = CAinitSslAdapter();
     if (result == CA_STATUS_OK)
     {
-        CAdeinitSslAdapter();
+        CAdeinitSslAdapter(true);
     }
     else
     {
@@ -1958,7 +1959,7 @@ static int testCAsetSslAdapterCallbacks()
         ret += 1;
     }
 
-    CAdeinitSslAdapter();
+    CAdeinitSslAdapter(true);
 
     return ret;
 }
@@ -2269,7 +2270,7 @@ static void * testCAencryptSsl(void * arg)
 
     CAcloseSslConnection(&serverAddr);
 
-    CAdeinitSslAdapter();
+    CAdeinitSslAdapter(true);
 
     socketClose();
 
@@ -2657,7 +2658,7 @@ static void * testCAdecryptSsl(void * arg)
 
     CAcloseSslConnection(&serverAddr);
 
-    CAdeinitSslAdapter();
+    CAdeinitSslAdapter(true);
 
     socketClose();
 
@@ -2739,7 +2740,7 @@ static int testCAdeinitSslAdapter()
 
     CAsetTlsCipherSuite(SSL_ECDHE_ECDSA_WITH_AES_128_CCM);
 
-    CAdeinitSslAdapter();
+    CAdeinitSslAdapter(true);
 
     if (g_caSslContext != NULL ||
         g_sslContextMutex != NULL)
@@ -2814,7 +2815,7 @@ static void * testServer(void * arg)
 
     CAcloseSslConnection(&serverAddr);
 
-    CAdeinitSslAdapter();
+    CAdeinitSslAdapter(true);
 
     socketClose_server();
 
@@ -3027,7 +3028,7 @@ static int testCAsetTlsCipherSuite()
         ret += 1;
     }
 
-    CAdeinitSslAdapter();
+    CAdeinitSslAdapter(true);
 
     return ret;
 }
@@ -3139,7 +3140,7 @@ TEST(TLSAdapter, Test_11)
 
     CAcloseSslConnection(&serverAddr);
 
-    CAdeinitSslAdapter();
+    CAdeinitSslAdapter(true);
 
     socketClose();