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

pnoltes pushed a commit to branch feature/pubsub_custom_serializers
in repository https://gitbox.apache.org/repos/asf/celix.git


The following commit(s) were added to 
refs/heads/feature/pubsub_custom_serializers by this push:
     new ccebdcd  fixes a race condition in uninstall bundle and when adding 
bundle listeners (storing bundle state)
ccebdcd is described below

commit ccebdcd1f1da85f31c6ed85488b1d147a3238731
Author: Pepijn Noltes <[email protected]>
AuthorDate: Mon Apr 20 19:22:10 2020 +0200

    fixes a race condition in uninstall bundle and when adding bundle listeners 
(storing bundle state)
---
 .../gtest/src/bundle_context_bundles_tests.cpp     |  1 +
 libs/framework/src/bundle_context.c                | 24 +++++++++----------
 libs/framework/src/framework.c                     | 27 ++++++++++++++++------
 3 files changed, 32 insertions(+), 20 deletions(-)

diff --git a/libs/framework/gtest/src/bundle_context_bundles_tests.cpp 
b/libs/framework/gtest/src/bundle_context_bundles_tests.cpp
index 27dcd74..c539c5f 100644
--- a/libs/framework/gtest/src/bundle_context_bundles_tests.cpp
+++ b/libs/framework/gtest/src/bundle_context_bundles_tests.cpp
@@ -329,6 +329,7 @@ TEST_F(CelixBundleContextBundlesTests, trackBundlesTest) {
 
     long bundleId1 = celix_bundleContext_installBundle(ctx, TEST_BND1_LOC, 
true);
     ASSERT_TRUE(bundleId1 >= 0);
+    celix_framework_waitForEmptyEventQueue(fw);
 
     /*
      * NOTE for bundles already installed (TEST_BND1) the callbacks are called 
on the
diff --git a/libs/framework/src/bundle_context.c 
b/libs/framework/src/bundle_context.c
index c2e2c36..0fe02be 100644
--- a/libs/framework/src/bundle_context.c
+++ b/libs/framework/src/bundle_context.c
@@ -562,19 +562,17 @@ long celix_bundleContext_trackBundlesWithOptions(
         const celix_bundle_tracking_options_t *opts) {
     long trackerId = -1;
     celix_bundle_context_bundle_tracker_entry_t *entry = calloc(1, 
sizeof(*entry));
-    if (entry != NULL) {
-        memcpy(&entry->opts, opts, sizeof(*opts));
-        entry->ctx = ctx;
-        entry->listener.handle = entry;
-        entry->listener.bundleChanged = bundleContext_bundleChanged;
-        fw_addBundleListener(ctx->framework, ctx->bundle, &entry->listener);
-
-        celixThreadMutex_lock(&ctx->mutex);
-        entry->trackerId = ctx->nextTrackerId++;
-        hashMap_put(ctx->bundleTrackers, (void*)entry->trackerId, entry);
-        celixThreadMutex_unlock(&ctx->mutex);
-        trackerId = entry->trackerId;
-    }
+    memcpy(&entry->opts, opts, sizeof(*opts));
+    entry->ctx = ctx;
+    entry->listener.handle = entry;
+    entry->listener.bundleChanged = bundleContext_bundleChanged;
+    fw_addBundleListener(ctx->framework, ctx->bundle, &entry->listener);
+
+    celixThreadMutex_lock(&ctx->mutex);
+    entry->trackerId = ctx->nextTrackerId++;
+    hashMap_put(ctx->bundleTrackers, (void*)entry->trackerId, entry);
+    celixThreadMutex_unlock(&ctx->mutex);
+    trackerId = entry->trackerId;
     return trackerId;
 }
 
diff --git a/libs/framework/src/framework.c b/libs/framework/src/framework.c
index f965508..4b11b3d 100644
--- a/libs/framework/src/framework.c
+++ b/libs/framework/src/framework.c
@@ -1191,6 +1191,7 @@ static celix_status_t 
fw_uninstallBundleEntry(celix_framework_t *framework, celi
             if (refreshStatus != CELIX_SUCCESS) {
                 printf("Could not refresh bundle");
             } else {
+                celix_framework_waitForEmptyEventQueue(framework); //to ensure 
that the uninstall event is triggered and handled
                 bundleArchive_destroy(archive);
                 status = CELIX_DO_IF(status, bundle_destroy(bnd));
             }
@@ -1502,7 +1503,14 @@ void fw_removeServiceListener(framework_pt framework, 
bundle_pt bundle __attribu
     celix_serviceRegistry_removeServiceListener(framework->registry, listener);
 }
 
+
 celix_status_t fw_addBundleListener(framework_pt framework, bundle_pt bundle, 
bundle_listener_pt listener) {
+    typedef struct {
+        celix_framework_bundle_entry_t* entry;
+        celix_bundle_state_e currentState;
+    } installed_bundle_entry_t;
+
+
     celix_status_t status = CELIX_SUCCESS;
     fw_bundle_listener_pt bundleListener = calloc(1, sizeof(*bundleListener));
     bundleListener->listener = listener;
@@ -1517,7 +1525,10 @@ celix_status_t fw_addBundleListener(framework_pt 
framework, bundle_pt bundle, bu
     for (int i = 0; i < size; ++i) {
         celix_framework_bundle_entry_t *entry = 
celix_arrayList_get(framework->installedBundles.entries, i);
         fw_bundleEntry_increaseUseCount(entry);
-        celix_arrayList_add(installedBundles, entry);
+        installed_bundle_entry_t* installedEntry = calloc(1, 
sizeof(*installedEntry));
+        installedEntry->entry = entry;
+        installedEntry->currentState = celix_bundle_getState(entry->bnd);
+        celix_arrayList_add(installedBundles, installedEntry);
     }
     celixThreadMutex_lock(&framework->bundleListenerLock);
     celix_arrayList_add(framework->bundleListeners, bundleListener);
@@ -1526,11 +1537,12 @@ celix_status_t fw_addBundleListener(framework_pt 
framework, bundle_pt bundle, bu
 
     //Calling bundle events for already installed bundles.
     for (int i =0 ; i < celix_arrayList_size(installedBundles); ++i) {
-        celix_framework_bundle_entry_t *entry = 
celix_arrayList_get(installedBundles, i);
-        celix_bundle_state_e state = celix_bundle_getState(entry->bnd);
+        installed_bundle_entry_t* installedEntry = 
celix_arrayList_get(installedBundles, i);
         celix_bundle_event_t event;
-        event.bundleId = entry->bndId;
-        event.bundleSymbolicName = 
(char*)celix_bundle_getSymbolicName(entry->bnd);
+        event.bundleId = installedEntry->entry->bndId;
+        event.bundleSymbolicName = 
(char*)celix_bundle_getSymbolicName(installedEntry->entry->bnd);
+
+        celix_bundle_state_e state = installedEntry->currentState;
 
         //note assuming bundle state values are increasing!
         if (state >= OSGI_FRAMEWORK_BUNDLE_INSTALLED) {
@@ -1545,7 +1557,8 @@ celix_status_t fw_addBundleListener(framework_pt 
framework, bundle_pt bundle, bu
             event.type = OSGI_FRAMEWORK_BUNDLE_EVENT_STARTED;
             listener->bundleChanged(listener, &event);
         }
-        fw_bundleEntry_decreaseUseCount(entry);
+        fw_bundleEntry_decreaseUseCount(installedEntry->entry);
+        free(installedEntry);
     }
     fw_bundleListener_decreaseUseCount(bundleListener);
     celix_arrayList_destroy(installedBundles);
@@ -2457,7 +2470,7 @@ long celix_framework_installBundle(celix_framework_t *fw, 
const char *bundleLoc,
     celix_status_t status = CELIX_SUCCESS;
 
     if (fw_installBundle(fw, &bnd, bundleLoc, NULL) == CELIX_SUCCESS) {
-        status = bundle_getBundleId(bnd, &bundleId); //TODO FIXME race 
condition with fw_installBundle, bundle can be uninstalled (no use count 
increase)
+        status = bundle_getBundleId(bnd, &bundleId);
         if (status == CELIX_SUCCESS && autoStart) {
             status = bundle_start(bnd);
         }

Reply via email to