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);
}