Merge pull request #337 from apache/hotfix/bundle_activator_issue
Fixes an issue in the bundle activator
diff --git a/libs/framework/gtest/CMakeLists.txt b/libs/framework/gtest/CMakeLists.txt
index e1045b7..d898d72 100644
--- a/libs/framework/gtest/CMakeLists.txt
+++ b/libs/framework/gtest/CMakeLists.txt
@@ -20,6 +20,7 @@
add_celix_bundle(simple_test_bundle3 NO_ACTIVATOR VERSION 1.0.0)
add_celix_bundle(bundle_with_exception SOURCES src/nop_activator.c VERSION 1.0.0)
add_celix_bundle(simple_cxx_bundle SOURCES src/HelloWorldCxxActivator.cc VERSION 1.0.0)
+add_celix_bundle(cmp_test_bundle SOURCES src/CmpTestBundleActivator.cc)
add_subdirectory(subdir) #simple_test_bundle4, simple_test_bundle5 and sublib
add_celix_bundle(unresolveable_bundle SOURCES src/nop_activator.c VERSION 1.0.0)
@@ -43,6 +44,7 @@
src/HelloWorldCxxActivator.cc
src/CxxFilterTestSuite.cc
src/CxxFrameworkFactoryTestSuite.cc
+ src/CxxBundleActivatorTestSuite.cc
)
target_link_libraries(test_framework Celix::framework CURL::libcurl GTest::gtest GTest::gtest_main)
@@ -50,15 +52,17 @@
target_include_directories(test_framework PRIVATE ../src)
celix_get_bundle_file(simple_cxx_bundle SIMPLE_CXX_BUNDLE_LOC)
+celix_get_bundle_file(cmp_test_bundle CMP_TEST_BUNDLE_LOC)
target_compile_definitions(test_framework PRIVATE
- -DSIMPLE_TEST_BUNDLE1_LOCATION="$<TARGET_PROPERTY:simple_test_bundle1,BUNDLE_FILE>"
- -DSIMPLE_TEST_BUNDLE2_LOCATION="$<TARGET_PROPERTY:simple_test_bundle2,BUNDLE_FILE>"
- -DSIMPLE_TEST_BUNDLE3_LOCATION="$<TARGET_PROPERTY:simple_test_bundle3,BUNDLE_FILE>"
- -DSIMPLE_TEST_BUNDLE4_LOCATION="$<TARGET_PROPERTY:simple_test_bundle4,BUNDLE_FILENAME>"
- -DSIMPLE_TEST_BUNDLE5_LOCATION="$<TARGET_PROPERTY:simple_test_bundle5,BUNDLE_FILENAME>"
- -DTEST_BUNDLE_WITH_EXCEPTION_LOCATION="$<TARGET_PROPERTY:bundle_with_exception,BUNDLE_FILE>"
- -DTEST_BUNDLE_UNRESOLVEABLE_LOCATION="$<TARGET_PROPERTY:unresolveable_bundle,BUNDLE_FILE>"
- -DSIMPLE_CXX_BUNDLE_LOC="${SIMPLE_CXX_BUNDLE_LOC}"
+ SIMPLE_TEST_BUNDLE1_LOCATION="$<TARGET_PROPERTY:simple_test_bundle1,BUNDLE_FILE>"
+ SIMPLE_TEST_BUNDLE2_LOCATION="$<TARGET_PROPERTY:simple_test_bundle2,BUNDLE_FILE>"
+ SIMPLE_TEST_BUNDLE3_LOCATION="$<TARGET_PROPERTY:simple_test_bundle3,BUNDLE_FILE>"
+ SIMPLE_TEST_BUNDLE4_LOCATION="$<TARGET_PROPERTY:simple_test_bundle4,BUNDLE_FILENAME>"
+ SIMPLE_TEST_BUNDLE5_LOCATION="$<TARGET_PROPERTY:simple_test_bundle5,BUNDLE_FILENAME>"
+ TEST_BUNDLE_WITH_EXCEPTION_LOCATION="$<TARGET_PROPERTY:bundle_with_exception,BUNDLE_FILE>"
+ TEST_BUNDLE_UNRESOLVEABLE_LOCATION="$<TARGET_PROPERTY:unresolveable_bundle,BUNDLE_FILE>"
+ SIMPLE_CXX_BUNDLE_LOC="${SIMPLE_CXX_BUNDLE_LOC}"
+ CMP_TEST_BUNDLE_LOC="${CMP_TEST_BUNDLE_LOC}"
)
configure_file(config.properties.in config.properties @ONLY)
diff --git a/libs/framework/gtest/src/CmpTestBundleActivator.cc b/libs/framework/gtest/src/CmpTestBundleActivator.cc
new file mode 100644
index 0000000..6e037e4
--- /dev/null
+++ b/libs/framework/gtest/src/CmpTestBundleActivator.cc
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "celix/BundleActivator.h"
+
+class TestCmp {
+public:
+ void setAnyService(const std::shared_ptr<void>& svc) {
+ std::lock_guard<std::mutex> lock{mutex};
+ anyService = svc;
+ }
+private:
+ std::mutex mutex{};
+ std::shared_ptr<void> anyService{};
+};
+
+class CmpTestBundleActivator {
+public:
+ explicit CmpTestBundleActivator(const std::shared_ptr<celix::BundleContext>& ctx) {
+ auto& cmp = ctx->getDependencyManager()->createComponent<TestCmp>();
+ tracker = ctx->trackAnyServices()
+ .addSetCallback(std::bind(&TestCmp::setAnyService, &cmp.getInstance(), std::placeholders::_1))
+ .build();
+ }
+private:
+ std::shared_ptr<celix::ServiceTracker<void>> tracker{};
+};
+
+CELIX_GEN_CXX_BUNDLE_ACTIVATOR(CmpTestBundleActivator)
\ No newline at end of file
diff --git a/libs/framework/gtest/src/CxxBundleActivatorTestSuite.cc b/libs/framework/gtest/src/CxxBundleActivatorTestSuite.cc
new file mode 100644
index 0000000..c38049d
--- /dev/null
+++ b/libs/framework/gtest/src/CxxBundleActivatorTestSuite.cc
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include "celix/FrameworkFactory.h"
+
+class CxxBundleActivatorTestSuite : public ::testing::Test {
+public:
+ CxxBundleActivatorTestSuite() {
+ fw = celix::createFramework();
+ ctx = fw->getFrameworkBundleContext();
+ }
+
+ std::shared_ptr<celix::Framework> fw{};
+ std::shared_ptr<celix::BundleContext> ctx{};
+};
+
+class TestInterface {
+public:
+ virtual ~TestInterface() noexcept = default;
+};
+
+class TestImpl : public TestInterface {
+public:
+ ~TestImpl() noexcept override = default;
+};
+
+TEST_F(CxxBundleActivatorTestSuite, InstallUninstallBundleWithCmpAndTracker) {
+ //When I install and uninstall a bundle with a component and tracker combination without asan issues (use after free)
+
+ auto reg = ctx->registerService<TestInterface>(std::make_shared<TestImpl>()).build();
+
+ auto bndId = ctx->installBundle(CMP_TEST_BUNDLE_LOC);
+ EXPECT_GE(bndId, 0);
+ ctx->uninstallBundle(bndId);
+
+}
+
diff --git a/libs/framework/include/celix/BundleActivator.h b/libs/framework/include/celix/BundleActivator.h
index 687475b..22b8881 100644
--- a/libs/framework/include/celix/BundleActivator.h
+++ b/libs/framework/include/celix/BundleActivator.h
@@ -84,6 +84,7 @@
std::weak_ptr<celix::BundleContext> ctx = data->ctx;
std::weak_ptr<celix::dm::DependencyManager> dm = data->ctx->getDependencyManager();
auto bndId = data->bndId;
+ data->bundleActivator.reset();
data->ctx->getDependencyManager()->clear();
delete data;
waitForExpired(bndId, ctx, "celix::BundleContext", ctx);