You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@celix.apache.org by pe...@apache.org on 2023/12/01 12:29:27 UTC

(celix) 04/11: [CID 331864]Fix race condition in http_admin.

This is an automated email from the ASF dual-hosted git repository.

pengzheng pushed a commit to branch support/2.4
in repository https://gitbox.apache.org/repos/asf/celix.git

commit b20883755c582592a0c3e725e5340e42b2ab2066
Author: PengZheng <ho...@gmail.com>
AuthorDate: Thu Nov 23 17:23:23 2023 +0800

    [CID 331864]Fix race condition in http_admin.
    
    (cherry picked from commit cc48c2433aecbfb7850d2e7f4f3d4437518f893b)
---
 bundles/http_admin/http_admin/src/http_admin.c     | 25 +++++++++-------------
 .../http_admin/http_admin/src/websocket_admin.c    | 20 +++++++++--------
 2 files changed, 21 insertions(+), 24 deletions(-)

diff --git a/bundles/http_admin/http_admin/src/http_admin.c b/bundles/http_admin/http_admin/src/http_admin.c
index a7e885b7..fb7ac6be 100755
--- a/bundles/http_admin/http_admin/src/http_admin.c
+++ b/bundles/http_admin/http_admin/src/http_admin.c
@@ -37,7 +37,7 @@ struct http_admin_manager {
     struct mg_context *mgCtx;
     char *root;
 
-    celix_thread_mutex_t admin_lock;  //protects below
+    celix_thread_rwlock_t admin_lock;  //protects below
 
     celix_http_info_service_t infoSvc;
     long infoSvcId;
@@ -70,7 +70,7 @@ http_admin_manager_t *httpAdmin_create(celix_bundle_context_t *context, char *ro
     admin->root = root;
     admin->infoSvcId = -1L;
 
-    status = celixThreadMutex_create(&admin->admin_lock, NULL);
+    status = celixThreadRwlock_create(&admin->admin_lock, NULL);
     admin->aliasList = celix_arrayList_create();
 
     if (status == CELIX_SUCCESS) {
@@ -93,7 +93,7 @@ http_admin_manager_t *httpAdmin_create(celix_bundle_context_t *context, char *ro
         if (admin->mgCtx != NULL) {
             mg_stop(admin->mgCtx);
         }
-        celixThreadMutex_destroy(&admin->admin_lock);
+        celixThreadRwlock_destroy(&admin->admin_lock);
 
         celix_arrayList_destroy(admin->aliasList);
         free(admin);
@@ -103,14 +103,13 @@ http_admin_manager_t *httpAdmin_create(celix_bundle_context_t *context, char *ro
 }
 
 void httpAdmin_destroy(http_admin_manager_t *admin) {
-    celixThreadMutex_lock(&(admin->admin_lock));
 
     if(admin->mgCtx != NULL) {
         mg_stop(admin->mgCtx);
     }
 
+    celixThreadRwlock_writeLock(&(admin->admin_lock));
     celix_bundleContext_unregisterService(admin->context, admin->infoSvcId);
-
     destroyServiceTree(&admin->http_svc_tree);
 
     //Destroy alias map by removing symbolic links first.
@@ -129,8 +128,8 @@ void httpAdmin_destroy(http_admin_manager_t *admin) {
     }
     celix_arrayList_destroy(admin->aliasList);
 
-    celixThreadMutex_unlock(&(admin->admin_lock));
-    celixThreadMutex_destroy(&(admin->admin_lock));
+    celixThreadRwlock_unlock(&(admin->admin_lock));
+    celixThreadRwlock_destroy(&(admin->admin_lock));
 
     free(admin->root);
     free(admin);
@@ -147,11 +146,10 @@ void http_admin_addHttpService(void *handle, void *svc, const celix_properties_t
     const char *uri = celix_properties_get(props, HTTP_ADMIN_URI, NULL);
 
     if(uri != NULL) {
-        celixThreadMutex_lock(&(admin->admin_lock));
+        celix_auto(celix_rwlock_wlock_guard_t) lock = celixRwlockWlockGuard_init(&(admin->admin_lock));
         if(!addServiceNode(&admin->http_svc_tree, uri, httpSvc)) {
             printf("HTTP service with URI %s already exists!\n", uri);
         }
-        celixThreadMutex_unlock(&(admin->admin_lock));
     }
 }
 
@@ -161,7 +159,7 @@ void http_admin_removeHttpService(void *handle, void *svc CELIX_UNUSED, const ce
     const char *uri = celix_properties_get(props, HTTP_ADMIN_URI, NULL);
 
     if(uri != NULL) {
-        celixThreadMutex_lock(&(admin->admin_lock));
+        celix_auto(celix_rwlock_wlock_guard_t) lock = celixRwlockWlockGuard_init(&(admin->admin_lock));
         service_tree_node_t *node = NULL;
 
         node = findServiceNodeInTree(&admin->http_svc_tree, uri);
@@ -171,8 +169,6 @@ void http_admin_removeHttpService(void *handle, void *svc CELIX_UNUSED, const ce
         } else {
             printf("Couldn't remove HTTP service with URI: %s, it doesn't exist\n", uri);
         }
-
-        celixThreadMutex_unlock(&(admin->admin_lock));
     }
 }
 
@@ -189,6 +185,7 @@ int http_request_handle(struct mg_connection *connection) {
             ret_status = 0; //... so return zero to let the civetweb server handle the request.
         }
         else {
+            celix_auto(celix_rwlock_rlock_guard_t) lock = celixRwlockRlockGuard_init(&(admin->admin_lock));
             const char *req_uri = ri->request_uri;
             node = findServiceNodeInTree(&admin->http_svc_tree, req_uri);
 
@@ -367,7 +364,7 @@ static void httpAdmin_updateInfoSvc(http_admin_manager_t *admin) {
     }
     fclose(stream);
 
-    celixThreadMutex_lock(&admin->admin_lock);
+    celix_auto(celix_rwlock_wlock_guard_t) lock = celixRwlockWlockGuard_init(&(admin->admin_lock));
     celix_bundleContext_unregisterService(admin->context, admin->infoSvcId);
 
     celix_properties_t *properties = celix_properties_create();
@@ -377,8 +374,6 @@ static void httpAdmin_updateInfoSvc(http_admin_manager_t *admin) {
     }
     admin->infoSvcId = celix_bundleContext_registerService(admin->context, &admin->infoSvc, HTTP_ADMIN_INFO_SERVICE_NAME, properties);
 
-    celixThreadMutex_unlock(&admin->admin_lock);
-
     free(resources_urls);
 }
 
diff --git a/bundles/http_admin/http_admin/src/websocket_admin.c b/bundles/http_admin/http_admin/src/websocket_admin.c
index 503bbf91..2cd8a453 100644
--- a/bundles/http_admin/http_admin/src/websocket_admin.c
+++ b/bundles/http_admin/http_admin/src/websocket_admin.c
@@ -35,7 +35,7 @@ struct websocket_admin_manager {
     struct mg_context *mg_ctx;
 
     service_tree_t sock_svc_tree;
-    celix_thread_mutex_t admin_lock;
+    celix_thread_rwlock_t admin_lock;
 };
 
 websocket_admin_manager_t *websocketAdmin_create(celix_bundle_context_t *context, struct mg_context *svr_ctx) {
@@ -49,7 +49,7 @@ websocket_admin_manager_t *websocketAdmin_create(celix_bundle_context_t *context
 
     admin->context = context;
     admin->mg_ctx = svr_ctx;
-    status = celixThreadMutex_create(&admin->admin_lock, NULL);
+    status = celixThreadRwlock_create(&admin->admin_lock, NULL);
 
     if(status != CELIX_SUCCESS) {
         //No need to destroy other things
@@ -60,14 +60,14 @@ websocket_admin_manager_t *websocketAdmin_create(celix_bundle_context_t *context
 }
 
 void websocketAdmin_destroy(websocket_admin_manager_t *admin) {
-    celixThreadMutex_lock(&(admin->admin_lock));
+    celixThreadRwlock_writeLock(&(admin->admin_lock));
 
     //Destroy tree with services
     destroyServiceTree(&admin->sock_svc_tree);
 
-    celixThreadMutex_unlock(&(admin->admin_lock));
+    celixThreadRwlock_unlock(&(admin->admin_lock));
 
-    celixThreadMutex_destroy(&(admin->admin_lock));
+    celixThreadRwlock_destroy(&(admin->admin_lock));
 
     free(admin);
 }
@@ -79,14 +79,13 @@ void websocket_admin_addWebsocketService(void *handle, void *svc, const celix_pr
     const char *uri = celix_properties_get(props, WEBSOCKET_ADMIN_URI, NULL);
 
     if(uri != NULL) {
-        celixThreadMutex_lock(&(admin->admin_lock));
+        celix_auto(celix_rwlock_wlock_guard_t) lock = celixRwlockWlockGuard_init(&(admin->admin_lock));
         if(addServiceNode(&admin->sock_svc_tree, uri, websockSvc)) {
             mg_set_websocket_handler(admin->mg_ctx, uri, websocket_connect_handler, websocket_ready_handler,
                                      websocket_data_handler, websocket_close_handler, admin);
         } else {
             printf("Websocket service with URI %s already exists!\n", uri);
         }
-        celixThreadMutex_unlock(&(admin->admin_lock));
     }
 }
 
@@ -96,7 +95,7 @@ void websocket_admin_removeWebsocketService(void *handle, void *svc CELIX_UNUSED
     const char *uri = celix_properties_get(props, WEBSOCKET_ADMIN_URI, NULL);
 
     if(uri != NULL) {
-        celixThreadMutex_lock(&(admin->admin_lock));
+        celix_auto(celix_rwlock_wlock_guard_t) lock = celixRwlockWlockGuard_init(&(admin->admin_lock));
         service_tree_node_t *node = NULL;
 
         node = findServiceNodeInTree(&admin->sock_svc_tree, uri);
@@ -107,7 +106,6 @@ void websocket_admin_removeWebsocketService(void *handle, void *svc CELIX_UNUSED
             printf("Couldn't remove websocket service with URI: %s, it doesn't exist\n", uri);
         }
 
-        celixThreadMutex_unlock(&(admin->admin_lock));
     }
 }
 
@@ -120,6 +118,7 @@ int websocket_connect_handler(const struct mg_connection *connection, void *hand
         const char *req_uri = ri->request_uri;
         service_tree_node_t *node = NULL;
 
+        celix_auto(celix_rwlock_rlock_guard_t) lock = celixRwlockRlockGuard_init(&(admin->admin_lock));
         node = findServiceNodeInTree(&admin->sock_svc_tree, req_uri);
 
         if(node != NULL) {
@@ -147,6 +146,7 @@ void websocket_ready_handler(struct mg_connection *connection, void *handle) {
         const char *req_uri = ri->request_uri;
         service_tree_node_t *node = NULL;
 
+        celix_auto(celix_rwlock_rlock_guard_t) lock = celixRwlockRlockGuard_init(&(admin->admin_lock));
         node = findServiceNodeInTree(&admin->sock_svc_tree, req_uri);
 
         if(node != NULL) {
@@ -169,6 +169,7 @@ int websocket_data_handler(struct mg_connection *connection, int op_code, char *
         const char *req_uri = ri->request_uri;
         service_tree_node_t *node = NULL;
 
+        celix_auto(celix_rwlock_rlock_guard_t) lock = celixRwlockRlockGuard_init(&(admin->admin_lock));
         node = findServiceNodeInTree(&admin->sock_svc_tree, req_uri);
 
         if(node != NULL) {
@@ -192,6 +193,7 @@ void websocket_close_handler(const struct mg_connection *connection, void *handl
         const char *req_uri = ri->request_uri;
         service_tree_node_t *node = NULL;
 
+        celix_auto(celix_rwlock_rlock_guard_t) lock = celixRwlockRlockGuard_init(&(admin->admin_lock));
         node = findServiceNodeInTree(&admin->sock_svc_tree, req_uri);
 
         if(node != NULL) {