Hold GetTopics API return until related code finishes in the other thread
authorjaesick.shin <jaesick.shin@samsung.com>
Sun, 4 Sep 2016 22:17:02 +0000 (07:17 +0900)
committerUze Choi <uzchoi@samsung.com>
Tue, 6 Sep 2016 10:23:53 +0000 (10:23 +0000)
Issue: Crash happen Get Topic just after Topic registration.
 (between RegistrerTopic and GetTopics/GetConsumerTopic APIs)

Fix: apply condition variable to RegistrerTopic API logic and
     GetTopics/GetConsumerTopic API logic.

Other Fixes:
 locking the NSProviderInterface.
 modify unittest for functions of 1 and 2.

Change-Id: Ia8e75d7b21198b3d4c3810050baa0867d60eeb78
Signed-off-by: jaesick.shin <jaesick.shin@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/11365
Reviewed-by: Uze Choi <uzchoi@samsung.com>
Tested-by: Uze Choi <uzchoi@samsung.com>
service/notification/src/common/NSConstants.h
service/notification/src/provider/NSProviderInterface.c
service/notification/src/provider/NSProviderTopic.c
service/notification/src/provider/NSProviderTopic.h
service/notification/unittest/NSProviderTest.cpp

index a6cc2a3..3c6d949 100644 (file)
@@ -266,7 +266,9 @@ typedef enum eTaskType
     TASK_DELETE_TOPIC = 11002,
     TASK_SUBSCRIBE_TOPIC = 11003,
     TASK_UNSUBSCRIBE_TOPIC = 11004,
-    TASK_POST_TOPIC = 11005
+    TASK_POST_TOPIC = 11005,
+    TASK_GET_TOPICS = 11006,
+    TAST_GET_CONSUMER_TOPICS = 11007
 
 } NSTaskType;
 
index 51d3785..0a956db 100644 (file)
 #include "cautilinterface.h"
 #include "NSProviderSystem.h"
 #include "oic_time.h"
+#include <pthread.h>
 
 bool initProvider = false;
 
 pthread_mutex_t nsInitMutex;
+pthread_cond_t nstopicCond;
 
 void initializeMutex()
 {
@@ -43,6 +45,31 @@ void initializeMutex()
     nsInitMutex = initMutex;
 }
 
+void NSInitialize()
+{
+    NS_LOG(DEBUG, "NSSetList - IN");
+
+    pthread_mutexattr_init(&NSCacheMutexAttr);
+    pthread_mutexattr_settype(&NSCacheMutexAttr, PTHREAD_MUTEX_RECURSIVE);
+    pthread_mutex_init(&NSCacheMutex, &NSCacheMutexAttr);
+    pthread_cond_init(&nstopicCond, NULL);
+
+    NSInitSubscriptionList();
+    NSInitTopicList();
+    NS_LOG(DEBUG, "NSSetList - OUT");
+}
+
+void NSDeinitailize()
+{
+    NSStorageDestroy(consumerSubList);
+    NSStorageDestroy(consumerTopicList);
+    NSStorageDestroy(registeredTopicList);
+
+    pthread_mutex_destroy(&NSCacheMutex);
+    pthread_mutexattr_destroy(&NSCacheMutexAttr);
+    pthread_cond_destroy(&nstopicCond);
+}
+
 NSResult NSStartProvider(NSProviderConfig config)
 {
     NS_LOG(DEBUG, "NSStartProvider - IN");
@@ -62,7 +89,7 @@ NSResult NSStartProvider(NSProviderConfig config)
         CARegisterNetworkMonitorHandler((CAAdapterStateChangedCB)NSProviderAdapterStateListener,
                 (CAConnectionStateChangedCB)NSProviderConnectionStateListener);
 
-        NSSetList();
+        NSInitialize();
         NSInitScheduler();
         NSStartScheduler();
 
@@ -79,29 +106,6 @@ NSResult NSStartProvider(NSProviderConfig config)
     return NS_OK;
 }
 
-void NSSetList()
-{
-    NS_LOG(DEBUG, "NSSetList - IN");
-
-    pthread_mutexattr_init(&NSCacheMutexAttr);
-    pthread_mutexattr_settype(&NSCacheMutexAttr, PTHREAD_MUTEX_RECURSIVE);
-    pthread_mutex_init(&NSCacheMutex, &NSCacheMutexAttr);
-
-    NSInitSubscriptionList();
-    NSInitTopicList();
-    NS_LOG(DEBUG, "NSSetList - OUT");
-}
-
-void NSDestroyList()
-{
-    NSStorageDestroy(consumerSubList);
-    NSStorageDestroy(consumerTopicList);
-    NSStorageDestroy(registeredTopicList);
-
-    pthread_mutex_destroy(&NSCacheMutex);
-    pthread_mutexattr_destroy(&NSCacheMutexAttr);
-}
-
 NSResult NSStopProvider()
 {
     NS_LOG(DEBUG, "NSStopProvider - IN");
@@ -115,7 +119,7 @@ NSResult NSStopProvider()
         NSRegisterSubscribeRequestCb((NSSubscribeRequestCallback)NULL);
         NSRegisterSyncCb((NSProviderSyncInfoCallback)NULL);
         NSStopScheduler();
-        NSDestroyList();
+        NSDeinitailize();
 
         initProvider = false;
     }
@@ -266,11 +270,18 @@ NSTopicLL * NSProviderGetConsumerTopics(const char * consumerId)
         return NULL;
     }
 
-    NSTopicLL * topics = NSProviderGetConsumerTopicsCacheData(registeredTopicList,
-            consumerTopicList, consumerId);
+    NSTopicSynchronization topics;
+    topics.consumerId = OICStrdup(consumerId);
+    topics.topics = NULL;
+    topics.condition = nstopicCond;
+
+    NSPushQueue(TOPIC_SCHEDULER, TAST_GET_CONSUMER_TOPICS, &topics);
+    pthread_cond_wait(&topics.condition, &nsInitMutex);
+    OICFree(topics.consumerId);
 
     pthread_mutex_unlock(&nsInitMutex);
-    return topics;
+    NS_LOG(DEBUG, "NSProviderGetConsumerTopics - OUT");
+    return topics.topics;
 }
 
 NSTopicLL * NSProviderGetTopics()
@@ -278,12 +289,17 @@ NSTopicLL * NSProviderGetTopics()
     NS_LOG(DEBUG, "NSProviderGetTopics - IN");
     pthread_mutex_lock(&nsInitMutex);
 
-    NSTopicLL * topics = NSProviderGetTopicsCacheData(registeredTopicList);
+    NSTopicSynchronization topics;
+    topics.consumerId = NULL;
+    topics.topics = NULL;
+    topics.condition = nstopicCond;
+
+    NSPushQueue(TOPIC_SCHEDULER, TASK_GET_TOPICS, &topics);
+    pthread_cond_wait(&topics.condition, &nsInitMutex);
 
     pthread_mutex_unlock(&nsInitMutex);
     NS_LOG(DEBUG, "NSProviderGetTopics - OUT");
-
-    return topics;
+    return topics.topics;
 }
 
 NSResult NSProviderRegisterTopic(const char * topicName)
index a16efa6..f7d9940 100644 (file)
@@ -21,6 +21,7 @@
 #include "NSProviderTopic.h"\r
 #include "oic_string.h"\r
 #include "oic_malloc.h"\r
+#include <pthread.h>\r
 \r
 NSResult NSSendTopicUpdation();\r
 \r
@@ -426,6 +427,25 @@ void * NSTopicSchedule(void * ptr)
                     NSFreeOCEntityHandlerRequest((OCEntityHandlerRequest*) node->taskData);\r
                 }\r
                     break;\r
+                case TASK_GET_TOPICS:\r
+                {\r
+                    NS_LOG(DEBUG, "TASK_GET_TOPICS : ");\r
+                    NSTopicSynchronization * topicData = (NSTopicSynchronization *) node->taskData;\r
+                    NSTopicLL * topics = NSProviderGetTopicsCacheData(registeredTopicList);\r
+                    topicData->topics = topics;\r
+                    pthread_cond_signal(&topicData->condition);\r
+                }\r
+                    break;\r
+                case TAST_GET_CONSUMER_TOPICS:\r
+                {\r
+                    NS_LOG(DEBUG, "TASK_GET_CONSUMER_TOPICS : ");\r
+                    NSTopicSynchronization * topicData = (NSTopicSynchronization *) node->taskData;\r
+                    NSTopicLL * topics = NSProviderGetConsumerTopicsCacheData(registeredTopicList,\r
+                                consumerTopicList, topicData->consumerId);\r
+                    topicData->topics = topics;\r
+                    pthread_cond_signal(&topicData->condition);\r
+                }\r
+                    break;\r
                 default:\r
                     break;\r
             }\r
index 20e416e..e14a8bf 100644 (file)
 #include "NSProviderResource.h"\r
 #include "NSProviderSubscription.h"\r
 \r
+typedef struct {\r
+    pthread_cond_t condition;\r
+    char * consumerId;\r
+    NSTopicLL * topics;\r
+} NSTopicSynchronization;\r
+\r
 NSCacheList * consumerTopicList;\r
 NSCacheList * registeredTopicList;\r
 \r
index ba46cc7..dd2238b 100755 (executable)
@@ -341,9 +341,6 @@ TEST_F(NotificationProviderTest, ExpectEqualAddedTopicsAndRegisteredTopics)
     NSProviderRegisterTopic(str.c_str());
     NSProviderRegisterTopic(str2.c_str());
 
-    std::unique_lock< std::mutex > lock{ mutexForCondition };
-    responseCon.wait_for(lock, std::chrono::milliseconds(1000));
-
     bool isSame = true;
     NSTopicLL * topics = NSProviderGetTopics();
 
@@ -378,9 +375,6 @@ TEST_F(NotificationProviderTest, ExpectEqualUnregisteredTopicsAndRegisteredTopic
     NSProviderRegisterTopic(str2.c_str());
     NSProviderUnregisterTopic(str2.c_str());
 
-    std::unique_lock< std::mutex > lock{ mutexForCondition };
-    responseCon.wait_for(lock, std::chrono::milliseconds(1000));
-
     bool isSame = true;
     NSTopicLL * topics = NSProviderGetTopics();