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