Commit 4df2dc79 authored by Iurii Metelytsia's avatar Iurii Metelytsia Committed by Nathan Heldt-Sheller

[IOT-3286] IoTivity may hang on exit

1. Reference counter has been added to ssl adapter.
2. Waiting for ReceiveThread when the caipserver is stopped added.
Signed-off-by: default avatarIurii Metelytsia <i.metelytsia@samsung.com>
Change-Id: I3ccf95ff1c851fe0d3e70f75ed00fdb1fce7bf82
parent a9e1dcab
......@@ -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.
......
......@@ -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);
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!");
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;
}
......
......@@ -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();
}
......
......@@ -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;
}
......
......@@ -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)
......
......@@ -547,7 +547,7 @@ CAResult_t CAStopTCP()
CAInitializeTCPGlobals();
#ifdef __WITH_TLS__
CAdeinitSslAdapter();
CAdeinitSslAdapter(true);
#endif
return CA_STATUS_OK;
......
......@@ -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();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment