You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@celix.apache.org by pn...@apache.org on 2021/01/15 19:47:15 UTC

[celix] branch feature/refactor_c_dep_man_service_trackers updated: Refactors depenency manager further, so that starting, stopping svc dep and registering svc is done async.

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

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


The following commit(s) were added to refs/heads/feature/refactor_c_dep_man_service_trackers by this push:
     new 07218d3  Refactors depenency manager further, so that starting, stopping svc dep and registering svc is done async.
07218d3 is described below

commit 07218d39bb7a5607f53180d928fa5e34917af2cf
Author: Pepijn Noltes <pe...@gmail.com>
AuthorDate: Fri Jan 15 20:47:00 2021 +0100

    Refactors depenency manager further, so that starting, stopping svc dep and registering svc is done async.
---
 .../pubsub/test/pstm_deadlock_test/test_runner.cc  |  41 +-
 .../gtest/src/DependencyManagerTestSuite.cc        |   7 +-
 .../gtest/src/bundle_context_services_test.cpp     |  97 ++++-
 libs/framework/include/celix/dm/Component.h        |  34 +-
 libs/framework/include/celix/dm/Component_Impl.h   |  43 +-
 .../framework/include/celix/dm/DependencyManager.h |  26 +-
 .../include/celix/dm/DependencyManager_Impl.h      |  66 ++-
 .../include/celix/dm/ServiceDependency_Impl.h      |  11 +-
 libs/framework/include/celix_bundle_activator.h    |   2 +-
 libs/framework/include/celix_bundle_context.h      |  15 +
 libs/framework/include/celix_dependency_manager.h  |   5 +
 libs/framework/include/celix_dm_component.h        |  12 +
 .../include/celix_dm_service_dependency.h          |   8 +
 libs/framework/src/bundle_context.c                |  17 +-
 libs/framework/src/dm_component_impl.c             | 473 ++++++++++++++-------
 libs/framework/src/dm_component_impl.h             |   2 +-
 libs/framework/src/dm_dependency_manager_impl.c    |  45 +-
 libs/framework/src/dm_service_dependency.c         | 139 ++++--
 libs/framework/src/dm_service_dependency_impl.h    |  26 +-
 libs/framework/src/framework.c                     |  10 +-
 libs/utils/src/array_list.c                        |   8 +-
 21 files changed, 772 insertions(+), 315 deletions(-)

diff --git a/bundles/pubsub/test/pstm_deadlock_test/test_runner.cc b/bundles/pubsub/test/pstm_deadlock_test/test_runner.cc
index abc5353..1b409be 100644
--- a/bundles/pubsub/test/pstm_deadlock_test/test_runner.cc
+++ b/bundles/pubsub/test/pstm_deadlock_test/test_runner.cc
@@ -23,26 +23,29 @@
 #include "pubsub/api.h"
 #include <unistd.h>
 #include <memory>
+#include <mutex>
 
 #include <gtest/gtest.h>
+#include <future>
 
 constexpr const char *deadlockSutBundleFile = DEADLOCK_SUT_BUNDLE_FILE;
 
 struct DeadlockTestSuite : public ::testing::Test {
     celix_framework_t *fw = NULL;
     celix_bundle_context_t *ctx = NULL;
-    std::unique_ptr<DependencyManager> mng = NULL;
+    std::shared_ptr<DependencyManager> mng = NULL;
     long sutBundleId = 0;
 
     DeadlockTestSuite() {
         celixLauncher_launch("config.properties", &fw);
         ctx = celix_framework_getFrameworkContext(fw);
-        mng = std::unique_ptr<DependencyManager>(new DependencyManager(ctx));
+        mng = std::shared_ptr<DependencyManager>(new DependencyManager(ctx));
         sutBundleId = celix_bundleContext_installBundle(ctx, deadlockSutBundleFile, false);
     }
 
     ~DeadlockTestSuite() override {
         celix_bundleContext_uninstallBundle(ctx, sutBundleId);
+        mng = nullptr;
         celixLauncher_stop(fw);
         celixLauncher_waitForShutdown(fw);
         celixLauncher_destroy(fw);
@@ -57,8 +60,10 @@ struct DeadlockTestSuite : public ::testing::Test {
 class DependencyCmp;
 
 struct activator {
-    Component<DependencyCmp> *cmp;
-    celix_bundle_context_t *ctx;
+    std::string cmpUUID{};
+    celix_bundle_context_t *ctx{};
+    std::promise<void> promise{};
+    std::shared_ptr<celix::dm::DependencyManager> mng{};
 };
 
 class IDependency {
@@ -86,14 +91,22 @@ public:
         return 1.0;
     }
 
-    void setPublisher(const pubsub_publisher_t *pub __attribute__((unused))) {
-        act->cmp->createCServiceDependency<pubsub_publisher_t>(PUBSUB_PUBLISHER_SERVICE_NAME)
-                .setVersionRange("[3.0.0,4)")
-                .setFilter("(topic=deadlock)(scope=scope2)")
-                .setStrategy(celix::dm::DependencyUpdateStrategy::suspend)
-                .setCallbacks([](const pubsub_publisher_t *, Properties&&) { std::cout << "success\n"; })
-                .setRequired(true)
-                .build();
+    void setPublisher(const pubsub_publisher_t *pub) {
+        if (pub == nullptr) {
+            return; //nothing on "unsetting" svc
+        }
+        auto cmp = act->mng->findComponent<DependencyCmp>(act->cmpUUID);
+        EXPECT_TRUE(cmp);
+        if (cmp) {
+            cmp->createCServiceDependency<pubsub_publisher_t>(PUBSUB_PUBLISHER_SERVICE_NAME)
+                    .setVersionRange("[3.0.0,4)")
+                    .setFilter("(topic=deadlock)(scope=scope2)")
+                    .setStrategy(celix::dm::DependencyUpdateStrategy::suspend)
+                    .setCallbacks([](const pubsub_publisher_t *, Properties&&) { std::cout << "success\n"; })
+                    .setRequired(true)
+                    .build();
+        }
+        act->promise.set_value();
     }
 
     int init() {
@@ -124,7 +137,8 @@ TEST_F(DeadlockTestSuite, test) {
 
     activator act{};
     act.ctx = ctx;
-    act.cmp = &cmp;
+    act.mng = mng;
+    act.cmpUUID = cmp.getUUID();
     cmp.getInstance().act = &act;
 
     cmp.createCServiceDependency<pubsub_publisher_t>(PUBSUB_PUBLISHER_SERVICE_NAME)
@@ -139,5 +153,6 @@ TEST_F(DeadlockTestSuite, test) {
 
     celix_bundleContext_startBundle(ctx, sutBundleId);
 
+    act.promise.get_future().wait(); //wait till setPublisher has added an service dependency (NOTE dep man is not thread safe!)
     mng->stop();
 }
diff --git a/libs/framework/gtest/src/DependencyManagerTestSuite.cc b/libs/framework/gtest/src/DependencyManagerTestSuite.cc
index bb4fec9..c68d25a 100644
--- a/libs/framework/gtest/src/DependencyManagerTestSuite.cc
+++ b/libs/framework/gtest/src/DependencyManagerTestSuite.cc
@@ -33,6 +33,8 @@ public:
         properties_set(properties, "LOGHELPER_ENABLE_STDOUT_FALLBACK", "true");
         properties_set(properties, "org.osgi.framework.storage.clean", "onFirstInit");
         properties_set(properties, "org.osgi.framework.storage", ".cacheBundleContextTestFramework");
+        properties_set(properties, "CELIX_LOGGING_DEFAULT_ACTIVE_LOG_LEVEL", "trace");
+
 
         fw = celix_frameworkFactory_createFramework(properties);
         ctx = framework_getContext(fw);
@@ -286,6 +288,7 @@ TEST_F(DependencyManagerTestSuite, AddSvcDepAfterBuild) {
 
     dep.build();
     dep.build(); //should be ok to call twice
+    celix_bundleContext_waitForEvents(ctx);
     ASSERT_EQ(1, count); //service dep build -> so count is 1;
 
     //create another service dep
@@ -304,9 +307,9 @@ TEST_F(DependencyManagerTestSuite, AddSvcDepAfterBuild) {
 
 TEST_F(DependencyManagerTestSuite, InCompleteBuildShouldNotLeak) {
     celix::dm::DependencyManager dm{ctx};
-    dm.createComponent<TestComponent>(std::make_shared<TestComponent>(), "test1"); //note not build
+    dm.createComponent<TestComponent>(std::make_shared<TestComponent>(), "test1"); //NOTE NOT BUILD
 
-    auto& cmp2 = dm.createComponent<Cmp1>(std::make_shared<Cmp1>(), "test2").build();
+    auto& cmp2 = dm.createComponent<Cmp1>(std::make_shared<Cmp1>(), "test2").build(); //NOTE BUILD
     cmp2.createCServiceDependency<TestService>("TestService").setFilter("(key=value"); //note not build
     cmp2.createServiceDependency<TestService>().setFilter("(key=value)"); //note not build
 
diff --git a/libs/framework/gtest/src/bundle_context_services_test.cpp b/libs/framework/gtest/src/bundle_context_services_test.cpp
index c12fc7b..a63049a 100644
--- a/libs/framework/gtest/src/bundle_context_services_test.cpp
+++ b/libs/framework/gtest/src/bundle_context_services_test.cpp
@@ -1196,19 +1196,35 @@ TEST_F(CelixBundleContextServicesTests, onlyCallAsyncCallbackWithAsyncApi) {
 }
 
 TEST_F(CelixBundleContextServicesTests, unregisterSvcBeforeAsyncRegistration) {
+    struct callback_data {
+        std::atomic<int> count{};
+        celix_bundle_context_t* ctx{nullptr};
+    };
+    callback_data cbData{};
+    cbData.ctx = ctx;
+
     celix_framework_fireGenericEvent(
             fw,
             -1,
             celix_bundle_getId(celix_framework_getFrameworkBundle(fw)),
             "registerAsync",
-            (void*)ctx,
+            (void*)&cbData,
             [](void *data) {
-                auto context = (celix_bundle_context_t*)data;
+                auto cbd = static_cast<struct callback_data*>(data);
+
+                celix_service_registration_options_t opts{};
+                opts.serviceName = "test-service";
+                opts.svc = (void*)0x42;
+                opts.asyncData = data;
+                opts.asyncCallback = [](void *data, long /*svcId*/) {
+                    auto* cbd = static_cast<struct callback_data*>(data);
+                    cbd->count.fetch_add(1);
+                };
 
                 //note register async. So a event on the event queue, but because this is done on the event queue this cannot be completed
-                long svcId = celix_bundleContext_registerServiceAsync(context, (void*)0x42, "test-service", nullptr);
+                long svcId = celix_bundleContext_registerServiceAsync(cbd->ctx, (void*)0x42, "test-service", nullptr);
 
-                celix_bundleContext_unregisterService(context, svcId); //trying to unregister still queued svc registration -> should cancel event.
+                celix_bundleContext_unregisterService(cbd->ctx, svcId); //trying to unregister still queued svc registration -> should cancel event.
             },
             nullptr,
             nullptr);
@@ -1216,67 +1232,110 @@ TEST_F(CelixBundleContextServicesTests, unregisterSvcBeforeAsyncRegistration) {
     celix_bundleContext_waitForEvents(ctx);
     long svcId = celix_bundleContext_findService(ctx, "test-service");
     EXPECT_LT(svcId, 0);
+    EXPECT_EQ(0, cbData.count.load()); //note create tracker canceled -> no callback
 }
 
 TEST_F(CelixBundleContextServicesTests, stopSvcTrackerBeforeAsyncTrackerIsCreated) {
+    struct callback_data {
+        std::atomic<int> count{};
+        celix_bundle_context_t* ctx{nullptr};
+    };
+    callback_data cbData{};
+    cbData.ctx = ctx;
+
     celix_framework_fireGenericEvent(
             fw,
             -1,
             celix_bundle_getId(celix_framework_getFrameworkBundle(fw)),
             "create tracker async",
-            (void*)ctx,
+            (void*)&cbData,
             [](void *data) {
-                auto context = (celix_bundle_context_t*)data;
+                auto cbd = static_cast<struct callback_data*>(data);
 
-                //note register async. So a event on the event queue, but because this is done on the event queue this cannot be completed
-                long trkId = celix_bundleContext_trackServicesAsync(context, "test-service", nullptr, nullptr,nullptr);
+                celix_service_tracking_options_t opts{};
+                opts.filter.serviceName = "test-service";
+                opts.trackerCreatedCallbackData = data;
+                opts.trackerCreatedCallback = [](void *data) {
+                    auto* cbd = static_cast<struct callback_data*>(data);
+                    cbd->count.fetch_add(1);
+                };
+
+                //note create async. So a event on the event queue, but because this is done on the event queue this cannot be completed
+                long trkId = celix_bundleContext_trackServicesWithOptionsAsync(cbd->ctx, &opts);
 
-                celix_bundleContext_stopTracker(context, trkId);
+                celix_bundleContext_stopTracker(cbd->ctx, trkId);
             },
             nullptr,
             nullptr);
 
     celix_bundleContext_waitForEvents(ctx);
+    EXPECT_EQ(0, cbData.count.load()); //note create tracker canceled -> no callback
 }
 
 TEST_F(CelixBundleContextServicesTests, stopBundleTrackerBeforeAsyncTrackerIsCreated) {
+    struct callback_data {
+        std::atomic<int> count{};
+        celix_bundle_context_t* ctx{nullptr};
+    };
+    callback_data cbData{};
+    cbData.ctx = ctx;
+
     celix_framework_fireGenericEvent(
             fw,
             -1,
             celix_bundle_getId(celix_framework_getFrameworkBundle(fw)),
             "create tracker async",
-            (void*)ctx,
+            (void*)&cbData,
             [](void *data) {
-                auto context = (celix_bundle_context_t*)data;
+                auto cbd = static_cast<struct callback_data*>(data);
 
-                //note register async. So a event on the event queue, but because this is done on the event queue this cannot be completed
-                long trkId = celix_bundleContext_trackBundlesAsync(context, nullptr, nullptr,nullptr);
+                celix_bundle_tracking_options_t opts{};
+                opts.trackerCreatedCallbackData = data;
+                opts.trackerCreatedCallback = [](void *data) {
+                    auto* cbd = static_cast<struct callback_data*>(data);
+                    cbd->count.fetch_add(1);
+                };
+
+                //note create async. So a event on the event queue, but because this is done on the event queue this cannot be completed
+                long trkId = celix_bundleContext_trackBundlesWithOptionsAsync(cbd->ctx, &opts);
 
-                celix_bundleContext_stopTracker(context, trkId);
+                celix_bundleContext_stopTracker(cbd->ctx, trkId);
             },
             nullptr,
             nullptr);
 
     celix_bundleContext_waitForEvents(ctx);
+    EXPECT_EQ(0, cbData.count.load()); //note create tracker canceled -> no callback
 }
 
 TEST_F(CelixBundleContextServicesTests, stopMetaTrackerBeforeAsyncTrackerIsCreated) {
+    struct callback_data {
+        std::atomic<int> count{};
+        celix_bundle_context_t* ctx{nullptr};
+    };
+    callback_data cbData{};
+    cbData.ctx = ctx;
+
     celix_framework_fireGenericEvent(
             fw,
             -1,
             celix_bundle_getId(celix_framework_getFrameworkBundle(fw)),
             "create tracker async",
-            (void*)ctx,
+            (void*)&cbData,
             [](void *data) {
-                auto context = (celix_bundle_context_t*)data;
+                auto cbd = static_cast<struct callback_data*>(data);
 
-                //note register async. So a event on the event queue, but because this is done on the event queue this cannot be completed
-                long trkId = celix_bundleContext_trackServiceTrackers(context, "test-service", nullptr, nullptr,nullptr);
+                //note create async. So a event on the event queue, but because this is done on the event queue this cannot be completed
+                long trkId = celix_bundleContext_trackServiceTrackersAsync(cbd->ctx, "test-service", nullptr, nullptr, nullptr, data, [](void *data) {
+                    auto* cbd = static_cast<struct callback_data*>(data);
+                    cbd->count.fetch_add(1);
+                });
 
-                celix_bundleContext_stopTracker(context, trkId);
+                celix_bundleContext_stopTracker(cbd->ctx, trkId);
             },
             nullptr,
             nullptr);
 
     celix_bundleContext_waitForEvents(ctx);
+    EXPECT_EQ(0, cbData.count.load()); //note create tracker canceled -> no callback
 }
\ No newline at end of file
diff --git a/libs/framework/include/celix/dm/Component.h b/libs/framework/include/celix/dm/Component.h
index c5d9c59..9a50c78 100644
--- a/libs/framework/include/celix/dm/Component.h
+++ b/libs/framework/include/celix/dm/Component.h
@@ -26,14 +26,16 @@
 #include <string>
 #include <vector>
 #include <atomic>
+#include <mutex>
 
 namespace celix { namespace dm {
 
     class BaseComponent {
     public:
-        BaseComponent(celix_bundle_context_t *con, celix_dependency_manager_t* cdm, const std::string &name) : context{con}, cDepMan{cdm}, cCmp{nullptr} {
-            this->cCmp = celix_dmComponent_create(this->context, name.c_str());
+        BaseComponent(celix_bundle_context_t *con, celix_dependency_manager_t* cdm, std::string name, std::string uuid) : context{con}, cDepMan{cdm}, cCmp{nullptr} {
+            this->cCmp = celix_dmComponent_createWithUUID(this->context, name.c_str(), uuid.empty() ? nullptr : uuid.c_str());
             celix_dmComponent_setImplementation(this->cCmp, this);
+            cmpUUID = std::string{celix_dmComponent_getUUID(this->cCmp)};
         }
         virtual ~BaseComponent() noexcept;
 
@@ -50,15 +52,19 @@ namespace celix { namespace dm {
          */
         celix_bundle_context_t* bundleContext() const { return this->context; }
 
+        const std::string& getUUID() const {
+            return cmpUUID;
+        }
+
         void runBuild();
     protected:
         std::vector<std::shared_ptr<BaseServiceDependency>> dependencies{};
         std::vector<std::shared_ptr<BaseProvidedService>> providedServices{};
 
-    private:
         celix_bundle_context_t* context;
         celix_dependency_manager_t* cDepMan;
         celix_dm_component_t *cCmp;
+        std::string cmpUUID{};
         std::atomic<bool> cmpAddedToDepMan{false};
     };
 
@@ -67,6 +73,7 @@ namespace celix { namespace dm {
     class Component : public BaseComponent {
         using type = T;
     private:
+        std::mutex instanceMutex{};
         std::unique_ptr<T> instance {nullptr};
         std::shared_ptr<T> sharedInstance {nullptr};
         std::vector<T> valInstance {};
@@ -80,24 +87,23 @@ namespace celix { namespace dm {
         int (T::*startFpNoExc)() = {};
         int (T::*stopFpNoExc)() = {};
         int (T::*deinitFpNoExc)() = {};
+
+        /**
+         * Ctor is private, use static create function member instead
+         * @param context
+         * @param cDepMan
+         * @param name
+         */
+        Component(celix_bundle_context_t *context, celix_dependency_manager_t* cDepMan, std::string name, std::string uuid);
     public:
-        Component(celix_bundle_context_t *context, celix_dependency_manager_t* cDepMan, const std::string &name);
         ~Component() override;
 
         /**
          * Creates a Component using the provided bundle context
          * and component name.
-         * Will use new(nothrow) if exceptions are disabled.
-         * @return newly created DM Component or nullptr
-         */
-        static Component<T>* create(celix_bundle_context_t*, celix_dependency_manager_t* cDepMan, const std::string &name);
-
-        /**
-         * Creates a Component using the provided bundle context.
-         * Will use new(nothrow) if exceptions are disabled.
-         * @return newly created DM Component or nullptr
+         * @return newly created DM Component.
          */
-        static Component<T>* create(celix_bundle_context_t*, celix_dependency_manager_t* cDepMan);
+        static std::shared_ptr<Component<T>> create(celix_bundle_context_t*, celix_dependency_manager_t* cDepMan, std::string name, std::string uuid);
 
         /**
          * Whether the component is valid. Invalid component can occurs when no new components can be created and
diff --git a/libs/framework/include/celix/dm/Component_Impl.h b/libs/framework/include/celix/dm/Component_Impl.h
index 4b80892..498b9a1 100644
--- a/libs/framework/include/celix/dm/Component_Impl.h
+++ b/libs/framework/include/celix/dm/Component_Impl.h
@@ -49,16 +49,19 @@ inline void BaseComponent::runBuild() {
     if (!alreadyAdded) {
         celix_dependencyManager_add(cDepMan, cCmp);
     }
-}
 
-inline BaseComponent::~BaseComponent() noexcept {
-    if (context != nullptr && !cmpAddedToDepMan) {
-        celix_dmComponent_destroy(cCmp);
+    if (context) {
+        auto *fw = celix_bundleContext_getFramework(context);
+        if (!celix_framework_isCurrentThreadTheEventLoop(fw)) {
+            celix_framework_waitForEmptyEventQueue(fw);
+        }
     }
 }
 
+inline BaseComponent::~BaseComponent() noexcept = default;
+
 template<class T>
-Component<T>::Component(celix_bundle_context_t *context, celix_dependency_manager_t* cDepMan, const std::string &name) : BaseComponent(context, cDepMan, name) {}
+Component<T>::Component(celix_bundle_context_t *context, celix_dependency_manager_t* cDepMan, std::string name, std::string uuid) : BaseComponent(context, cDepMan, std::move(name), std::move(uuid)) {}
 
 template<class T>
 Component<T>::~Component() = default;
@@ -161,19 +164,19 @@ Component<T>& Component<T>::remove(CServiceDependency<T,I>& dep) {
 }
 
 template<class T>
-Component<T>* Component<T>::create(celix_bundle_context_t *context, celix_dependency_manager_t* cDepMan) {
-    std::string name = typeName<T>();
-    return Component<T>::create(context, cDepMan, name);
-}
-
-template<class T>
-Component<T>* Component<T>::create(celix_bundle_context_t *context, celix_dependency_manager_t* cDepMan, const std::string &name) {
-    static Component<T> invalid{nullptr, nullptr, std::string{}};
-    Component<T>* cmp = new (std::nothrow) Component<T>(context, cDepMan, name);
-    if (cmp == nullptr) {
-        cmp = &invalid;
-    }
-    return cmp;
+std::shared_ptr<Component<T>> Component<T>::create(celix_bundle_context_t *context, celix_dependency_manager_t* cDepMan, std::string name, std::string uuid) {
+    std::string cmpName = name.empty() ? celix::dm::typeName<T>() : std::move(name);
+    return std::shared_ptr<Component<T>>{new Component<T>(context, cDepMan, std::move(cmpName), std::move(uuid)), [](Component<T>* cmp){
+        if (cmp->cmpAddedToDepMan) {
+            celix_dependencyManager_removeWithoutDestroy(cmp->cDepMan, cmp->cCmp); //remove
+        }
+        //NOTE using a callback of async destroy to ensure that the cmp instance is still exist while the
+        //dm component is async disabled and destroyed.
+        celix_dmComponent_destroyAsync(cmp->cCmp, cmp, [](void *data) {
+            auto* c = static_cast<Component<T>*>(data);
+            delete c;
+        });
+    }};
 }
 
 template<class T>
@@ -198,6 +201,7 @@ createInstance() {
 
 template<class T>
 T& Component<T>::getInstance() {
+    std::lock_guard<std::mutex> lck{instanceMutex};
     if (!valInstance.empty()) {
         return valInstance.front();
     } else if (sharedInstance) {
@@ -213,6 +217,7 @@ T& Component<T>::getInstance() {
 
 template<class T>
 Component<T>& Component<T>::setInstance(std::shared_ptr<T> inst) {
+    std::lock_guard<std::mutex> lck{instanceMutex};
     this->valInstance.clear();
     this->instance = std::unique_ptr<T> {nullptr};
     this->sharedInstance = std::move(inst);
@@ -221,6 +226,7 @@ Component<T>& Component<T>::setInstance(std::shared_ptr<T> inst) {
 
 template<class T>
 Component<T>& Component<T>::setInstance(std::unique_ptr<T>&& inst) {
+    std::lock_guard<std::mutex> lck{instanceMutex};
     this->valInstance.clear();
     this->sharedInstance = std::shared_ptr<T> {nullptr};
     this->instance = std::move(inst);
@@ -229,6 +235,7 @@ Component<T>& Component<T>::setInstance(std::unique_ptr<T>&& inst) {
 
 template<class T>
 Component<T>& Component<T>::setInstance(T&& inst) {
+    std::lock_guard<std::mutex> lck{instanceMutex};
     this->instance = std::unique_ptr<T> {nullptr};
     this->sharedInstance = std::shared_ptr<T> {nullptr};
     this->valInstance.clear();
diff --git a/libs/framework/include/celix/dm/DependencyManager.h b/libs/framework/include/celix/dm/DependencyManager.h
index 6dc8a94..1f2688e 100644
--- a/libs/framework/include/celix/dm/DependencyManager.h
+++ b/libs/framework/include/celix/dm/DependencyManager.h
@@ -57,7 +57,7 @@ namespace celix { namespace dm {
          */
         template<class T>
         typename std::enable_if<std::is_default_constructible<T>::value, Component<T>&>::type
-        createComponent(std::string name = std::string{});
+        createComponent(std::string name = std::string{}, std::string uuid = {});
 
         /**
          * Creates and adds a new DM Component for a component of type T and setting
@@ -66,7 +66,7 @@ namespace celix { namespace dm {
          * @return Returns a reference to the DM Component
          */
         template<class T>
-        Component<T>& createComponent(std::unique_ptr<T>&& rhs, std::string name = std::string{});
+        Component<T>& createComponent(std::unique_ptr<T>&& rhs, std::string name = std::string{}, std::string uuid = {});
 
         /**
          * Creates and adds a new DM Component for a component of type T and setting
@@ -75,7 +75,7 @@ namespace celix { namespace dm {
          * @return Returns a reference to the DM Component
          */
         template<class T>
-        Component<T>& createComponent(std::shared_ptr<T> rhs, std::string name = std::string{});
+        Component<T>& createComponent(std::shared_ptr<T> rhs, std::string name = std::string{}, std::string uuid = {});
 
         /**
          * Creates and adds a new DM Component for a component of type T and setting
@@ -84,7 +84,7 @@ namespace celix { namespace dm {
          * @return Returns a reference to the DM Component
          */
         template<class T>
-        Component<T>& createComponent(T rhs, std::string name = std::string{});
+        Component<T>& createComponent(T rhs, std::string name = std::string{}, std::string uuid = {});
 
         /**
          * Build the dependency manager.
@@ -127,9 +127,25 @@ namespace celix { namespace dm {
          * Returns the nr of configured components for this dependency manager.
          */
         std::size_t getNrOfComponents() const;
+
+        /**
+         * Tries to find the component with UUID and staticly cast it to
+         * dm component of type T
+         * @return pointer to found component or null if the component cannot be found.
+         *
+         * Note: DependencyManager is not thread safe!
+         */
+        template<typename T>
+        std::shared_ptr<Component<T>> findComponent(const std::string& uuid) const;
     private:
         template<class T>
-        Component<T>& createComponentInternal(std::string name);
+        Component<T>& createComponentInternal(std::string name, std::string uuid);
+
+        /**
+         * Wait until current Celix event queue is empty.
+         * Note: will just return if the current thread is the Celix event thread
+         */
+        void wait() const;
 
         std::shared_ptr<celix_bundle_context_t> context;
         std::shared_ptr<celix_dependency_manager_t> cDepMan;
diff --git a/libs/framework/include/celix/dm/DependencyManager_Impl.h b/libs/framework/include/celix/dm/DependencyManager_Impl.h
index 2d3b578..aaff50a 100644
--- a/libs/framework/include/celix/dm/DependencyManager_Impl.h
+++ b/libs/framework/include/celix/dm/DependencyManager_Impl.h
@@ -17,6 +17,7 @@
  * under the License.
  */
 
+#include <cassert>
 #include "DependencyManager.h"
 
 using namespace celix::dm;
@@ -25,15 +26,16 @@ inline DependencyManager::DependencyManager(celix_bundle_context_t *ctx) :
     context{ctx, [](celix_bundle_context_t*){/*nop*/}},
     cDepMan{celix_bundleContext_getDependencyManager(ctx), [](celix_dependency_manager_t*){/*nop*/}} {}
 
-inline DependencyManager::~DependencyManager() {/*nop*/}
+inline DependencyManager::~DependencyManager() {
+    clear();
+}
 
 template<class T>
-Component<T>& DependencyManager::createComponentInternal(std::string name) {
-    Component<T>* cmp = name.empty() ?
-                        Component<T>::create(this->context.get(), this->cDepMan.get()) :
-                        Component<T>::create(this->context.get(), this->cDepMan.get(), name);
+Component<T>& DependencyManager::createComponentInternal(std::string name, std::string uuid) {
+    auto cmp = Component<T>::create(this->context.get(), this->cDepMan.get(), std::move(name), std::move(uuid));
     if (cmp->isValid()) {
-        this->components.push_back(std::shared_ptr<BaseComponent>{cmp});
+        auto baseCmp = std::static_pointer_cast<BaseComponent>(cmp);
+        this->components.push_back(baseCmp);
     }
 
     return *cmp;
@@ -42,23 +44,23 @@ Component<T>& DependencyManager::createComponentInternal(std::string name) {
 template<class T>
 inline
 typename std::enable_if<std::is_default_constructible<T>::value, Component<T>&>::type
-DependencyManager::createComponent(std::string name) {
-    return createComponentInternal<T>(name);
+DependencyManager::createComponent(std::string name, std::string uuid) {
+    return createComponentInternal<T>(name, uuid);
 }
 
 template<class T>
-Component<T>& DependencyManager::createComponent(std::unique_ptr<T>&& rhs, std::string name) {
-    return createComponentInternal<T>(name).setInstance(std::move(rhs));
+Component<T>& DependencyManager::createComponent(std::unique_ptr<T>&& rhs, std::string name, std::string uuid) {
+    return createComponentInternal<T>(name, uuid).setInstance(std::move(rhs));
 }
 
 template<class T>
-Component<T>& DependencyManager::createComponent(std::shared_ptr<T> rhs, std::string name) {
-    return createComponentInternal<T>(name).setInstance(rhs);
+Component<T>& DependencyManager::createComponent(std::shared_ptr<T> rhs, std::string name, std::string uuid) {
+    return createComponentInternal<T>(name, uuid).setInstance(rhs);
 }
 
 template<class T>
-Component<T>& DependencyManager::createComponent(T rhs, std::string name) {
-    return createComponentInternal<T>(name).setInstance(std::forward<T>(rhs));
+Component<T>& DependencyManager::createComponent(T rhs, std::string name, std::string uuid) {
+    return createComponentInternal<T>(name, uuid).setInstance(std::forward<T>(rhs));
 }
 
 inline void DependencyManager::start() {
@@ -69,16 +71,33 @@ inline void DependencyManager::build() {
     for (auto& cmp : components) {
         cmp->runBuild();
     }
+    wait();
 }
 
 template<typename T>
 void DependencyManager::destroyComponent(Component<T> &component) {
-    celix_dependencyManager_remove(cDepMan.get(), component.cComponent());
+    for (auto it = components.begin(); it != components.end(); ++it) {
+        if ( (*it).get() == &component) {
+            //found
+            components.erase(it);
+            break;
+        }
+    }
+    wait();
 }
 
 inline void DependencyManager::clear() {
-    celix_dependencyManager_removeAllComponents(cDepMan.get());
     components.clear();
+    wait();
+}
+
+inline void DependencyManager::wait() const {
+    if (context) {
+        auto *fw = celix_bundleContext_getFramework(context.get());
+        if (!celix_framework_isCurrentThreadTheEventLoop(fw)) {
+            celix_framework_waitForEmptyEventQueue(fw);
+        }
+    }
 }
 
 inline void DependencyManager::stop() {
@@ -89,3 +108,18 @@ inline std::size_t DependencyManager::getNrOfComponents() const {
     return celix_dependencyManager_nrOfComponents(cDepMan.get());
 }
 
+template<typename T>
+inline std::shared_ptr<Component<T>> DependencyManager::findComponent(const std::string& uuid) const  {
+    std::shared_ptr<BaseComponent> found{nullptr};
+    for (const auto& cmp : components) {
+        if (cmp->getUUID() == uuid) {
+            found = cmp;
+        }
+    }
+    if (found) {
+        return std::static_pointer_cast<Component<T>>(found);
+    } else {
+        return nullptr;
+    }
+}
+
diff --git a/libs/framework/include/celix/dm/ServiceDependency_Impl.h b/libs/framework/include/celix/dm/ServiceDependency_Impl.h
index a9dd5d2..c2f6824 100644
--- a/libs/framework/include/celix/dm/ServiceDependency_Impl.h
+++ b/libs/framework/include/celix/dm/ServiceDependency_Impl.h
@@ -22,6 +22,8 @@
 #include <cstring>
 #include "celix_constants.h"
 #include "celix_properties.h"
+#include "celix_bundle_context.h"
+#include "celix_framework.h"
 #include "ServiceDependency.h"
 
 
@@ -32,11 +34,18 @@ inline void BaseServiceDependency::runBuild() {
     if (!alreadyAdded) {
         celix_dmComponent_addServiceDependency(cCmp, cServiceDep);
     }
+    auto* ctx = celix_dmComponent_getBundleContext(cCmp);
+    if (ctx != nullptr) {
+        auto* fw = celix_bundleContext_getFramework(ctx);
+        if (!celix_framework_isCurrentThreadTheEventLoop(fw)) {
+            celix_framework_waitForEmptyEventQueue(fw);
+        }
+    }
 }
 
 inline BaseServiceDependency::~BaseServiceDependency() noexcept {
     if (!depAddedToCmp) {
-        celix_dmServiceDependency_destroy(cServiceDep);
+        celix_dmServiceDependency_destroyAsync(cServiceDep, nullptr, nullptr);
     }
 }
 
diff --git a/libs/framework/include/celix_bundle_activator.h b/libs/framework/include/celix_bundle_activator.h
index ab02ed2..37c978c 100644
--- a/libs/framework/include/celix_bundle_activator.h
+++ b/libs/framework/include/celix_bundle_activator.h
@@ -194,7 +194,7 @@ extern "C" celix_status_t bundleActivator_start(void *userData, celix_bundle_con
 extern "C" celix_status_t bundleActivator_stop(void *userData, celix_bundle_context_t*) {                              \
     auto* data = static_cast<BundleActivatorData*>(userData);                                                          \
     if (data != nullptr) {                                                                                             \
-        data->mng->stop();                                                                                             \
+        data->mng->clear()                                                                                             \
         data->activator = nullptr;                                                                                     \
         data->mng = nullptr;                                                                                           \
     }                                                                                                                  \
diff --git a/libs/framework/include/celix_bundle_context.h b/libs/framework/include/celix_bundle_context.h
index b99c8b5..af010ea 100644
--- a/libs/framework/include/celix_bundle_context.h
+++ b/libs/framework/include/celix_bundle_context.h
@@ -177,6 +177,10 @@ typedef struct celix_service_registration_options {
     /**
     * Async callback. Will be called after the a service is registered in the service registry using a async call.
     * Will be called on the Celix event loop.
+     *
+     * If a asyns service registration is combined with a _sync_ service unregistration, it can happen that
+     * unregistration happens before the registration event is processed. In this case the asyncCallback
+     * will not be called.
     */
     void (*asyncCallback)(void *data, long serviceId) OPTS_INIT;
 } celix_service_registration_options_t;
@@ -524,6 +528,10 @@ typedef struct celix_service_tracking_options {
 
     /**
      * The callback called when the tracker has ben created (and is active) when using a async call.
+     *
+     * If a asyns track service is combined with a _sync_ stop tracker, it can happen that
+     * "stop tracker" happens before the "create tracker" event is processed. In this case the asyncCallback
+     * will not be called.
      */
     void (*trackerCreatedCallback)(void *trackerCreatedCallbackData) OPTS_INIT;
 } celix_service_tracking_options_t;
@@ -958,6 +966,10 @@ typedef struct celix_bundle_tracker_options {
     /**
      * The callback called when the tracker has ben created (and is active) when using the
      * track bundles ascync calls.
+     *
+     * If a asyns track service is combined with a _sync_ stop tracker, it can happen that
+     * "stop tracker" happens before the "create tracker" event is processed. In this case the asyncCallback
+     * will not be called.
      */
     void (*trackerCreatedCallback)(void *trackerCreatedCallbackData) OPTS_INIT;
 } celix_bundle_tracking_options_t;
@@ -1086,6 +1098,9 @@ typedef struct celix_service_tracker_info {
  * @param trackerRemove Called when a service tracker is removed, which tracks the provided service name
  * @param doneCallbackData call back data argument provided to the done callback function.
  * @param doneCallback If not NULL will be called when the service tracker tracker is created.
+ *                          If a asyns track service is combined with a _sync_ stop tracker, it can happen that
+ *                          "stop tracker" happens before the "create tracker" event is processed.
+ *                          In this case the doneCallback will not be called.
  * @return The tracker id or <0 if something went wrong (will log an error).
  */
 long celix_bundleContext_trackServiceTrackersAsync(
diff --git a/libs/framework/include/celix_dependency_manager.h b/libs/framework/include/celix_dependency_manager.h
index 2bff28b..630172f 100644
--- a/libs/framework/include/celix_dependency_manager.h
+++ b/libs/framework/include/celix_dependency_manager.h
@@ -42,6 +42,11 @@ celix_status_t celix_dependencyManager_add(celix_dependency_manager_t *manager,
 celix_status_t celix_dependencyManager_remove(celix_dependency_manager_t *manager, celix_dm_component_t *component);
 
 /**
+ * Removes a DM component from the dependency manager.
+ */
+celix_status_t celix_dependencyManager_removeWithoutDestroy(celix_dependency_manager_t *manager, celix_dm_component_t *component);
+
+/**
  * Removes all DM components from the dependency manager
  */
 celix_status_t celix_dependencyManager_removeAllComponents(celix_dependency_manager_t *manager);
diff --git a/libs/framework/include/celix_dm_component.h b/libs/framework/include/celix_dm_component.h
index 3998086..244111e 100644
--- a/libs/framework/include/celix_dm_component.h
+++ b/libs/framework/include/celix_dm_component.h
@@ -69,6 +69,13 @@ const char* celix_dmComponent_getUUID(celix_dm_component_t* cmp);
 void celix_dmComponent_destroy(celix_dm_component_t *cmp);
 
 /**
+ * Destroys a DM Component on the event thread.
+ * Will call doneCallback when done.
+ *
+ */
+void celix_dmComponent_destroyAsync(celix_dm_component_t *cmp, void *doneData, void (*doneCallback)(void*));
+
+/**
  * Specify if a default 'service.lang=C' should be added to the properties of interfaces if no 'service.lang' has been
  * provided. Default is false. Note that this should be set before using component_addInterface.
  */
@@ -162,6 +169,11 @@ bool celix_dmComponent_isActive(celix_dm_component_t *component);
  */
 void celix_dmComponent_destroyComponentInfo(dm_component_info_pt info);
 
+/**
+ * Returns the string value of a provided state
+ */
+const char* celix_dmComponent_stateToString(celix_dm_component_state_t state);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/libs/framework/include/celix_dm_service_dependency.h b/libs/framework/include/celix_dm_service_dependency.h
index 9ef51a8..dd9732d 100644
--- a/libs/framework/include/celix_dm_service_dependency.h
+++ b/libs/framework/include/celix_dm_service_dependency.h
@@ -78,6 +78,14 @@ celix_dm_service_dependency_t* celix_dmServiceDependency_create(void);
  */
 void celix_dmServiceDependency_destroy(celix_dm_service_dependency_t *dep);
 
+void celix_dmServiceDependency_destroyAsync(celix_dm_service_dependency_t *dep, void *doneData, void (*doneCallback)(void*));
+
+/**
+ * Note free resource of dm service dependency.
+ * Should only be called on a disabled service dependency.
+ */
+void celix_dmServiceDependency_free(celix_dm_service_dependency_t *dep);
+
 /**
  * Specify if the service dependency is required. default is false
  */
diff --git a/libs/framework/src/bundle_context.c b/libs/framework/src/bundle_context.c
index ce4d4ce..0bdf1e7 100644
--- a/libs/framework/src/bundle_context.c
+++ b/libs/framework/src/bundle_context.c
@@ -670,6 +670,9 @@ void celix_bundleContext_trackBundlesWithOptionsCallback(void *data) {
         free(entry);
     } else {
         fw_addBundleListener(entry->ctx->framework, entry->ctx->bundle, &entry->listener);
+        if (entry->opts.trackerCreatedCallback) {
+            entry->opts.trackerCreatedCallback(entry->opts.trackerCreatedCallbackData);
+        }
     }
 
 }
@@ -692,9 +695,8 @@ static long celix_bundleContext_trackBundlesWithOptionsInternal(
     trackerId = entry->trackerId;
     celixThreadMutex_unlock(&ctx->mutex);
 
-    void (*trackerCreatedCallback)(void *trackerCreatedCallbackData) = NULL;
-    if (async) { //note only using the async callback if this is a async call.
-        trackerCreatedCallback = opts->trackerCreatedCallback;
+    if (!async) { //note only using the async callback if this is a async call.
+        entry->opts.callbackHandle = NULL;
     }
     long id = celix_framework_fireGenericEvent(
             ctx->framework,
@@ -703,8 +705,8 @@ static long celix_bundleContext_trackBundlesWithOptionsInternal(
             "add bundle listener",
             entry,
             celix_bundleContext_trackBundlesWithOptionsCallback,
-            opts->trackerCreatedCallbackData,
-            trackerCreatedCallback);
+            NULL,
+            NULL);
 
     if (!async) {
         celix_framework_waitForGenericEvent(ctx->framework, id);
@@ -1383,12 +1385,11 @@ static void celix_bundleContext_doneCreatingTrackerOnEventLoop(void *data) {
     celixThreadMutex_lock(&entry->ctx->mutex);
     bool cancelled = entry->cancelled;
     celixThreadMutex_unlock(&entry->ctx->mutex);
-    if (entry->trackerCreatedCallback != NULL) {
-        entry->trackerCreatedCallback(entry->trackerCreatedCallbackData);
-    }
     if (cancelled) {
         //tracker creation cancelled -> entry already removed from map, but memory needs to be freed.
         free(entry);
+    } else if (entry->trackerCreatedCallback != NULL) {
+        entry->trackerCreatedCallback(entry->trackerCreatedCallbackData);
     }
 }
 
diff --git a/libs/framework/src/dm_component_impl.c b/libs/framework/src/dm_component_impl.c
index 08a4e01..c04e617 100644
--- a/libs/framework/src/dm_component_impl.c
+++ b/libs/framework/src/dm_component_impl.c
@@ -48,15 +48,23 @@ struct celix_dm_component_struct {
     celix_array_list_t* providedInterfaces; //type = dm_interface_t*
     celix_array_list_t* dependencies; //type = celix_dm_service_dependency_t*
 
+    /**
+     * Removed dependencies, which are potential still being stopped async
+     */
+    celix_array_list_t* removedDependencies; //type = celix_dm_service_dependency_t*
+
     celix_dm_component_state_t state;
 
     /**
-     * Nr of active set, add or remove svc calls in progress.
+     * Nr of svc depedencies in progress:
+     *  - this means a set, add or remove svc callback are in progress and/or
+     *  - a service dependency is being stopped
      * Should be 0 before destroying cmp or removing service dependencies
      */
-    size_t nrOfSetAddRemCallsInProgress;
+    size_t nrOfSvcDepependenciesInProgress;
 
-    bool isStarted;
+
+    bool isEnabled;
 };
 
 typedef struct dm_interface_struct {
@@ -66,19 +74,21 @@ typedef struct dm_interface_struct {
     long svcId;
 } dm_interface_t;
 
-static celix_status_t component_registerServices(celix_dm_component_t *component);
-static celix_status_t component_unregisterServices(celix_dm_component_t *component);
-static bool component_areAllRequiredServiceDependenciesResolved(celix_dm_component_t *component);
-static celix_status_t component_performTransition(celix_dm_component_t *component, celix_dm_component_state_t oldState, celix_dm_component_state_t newState, bool *transition);
-static celix_status_t component_calculateNewState(celix_dm_component_t *component, celix_dm_component_state_t currentState, celix_dm_component_state_t *newState);
-static celix_status_t component_handleChange(celix_dm_component_t *component);
-static celix_status_t component_handleAdd(celix_dm_component_t *component, const celix_dm_event_t* event);
-static celix_status_t component_handleRemove(celix_dm_component_t *component, const celix_dm_event_t* event);
-static celix_status_t component_handleSet(celix_dm_component_t *component, const celix_dm_event_t* event);
-static celix_status_t component_startDependencies(celix_dm_component_t *component);
-static celix_status_t component_suspend(celix_dm_component_t *component, celix_dm_service_dependency_t *dependency);
-static celix_status_t component_resume(celix_dm_component_t *component, celix_dm_service_dependency_t *dependency);
-static celix_status_t celix_dmComponent_stop(celix_dm_component_t *component);
+static celix_status_t celix_dmComponent_registerServices(celix_dm_component_t *component);
+static celix_status_t celix_dmComponent_unregisterServices(celix_dm_component_t *component);
+static bool celix_dmComponent_areAllRequiredServiceDependenciesResolved(celix_dm_component_t *component);
+static celix_status_t celix_dmComponent_performTransition(celix_dm_component_t *component, celix_dm_component_state_t oldState, celix_dm_component_state_t newState, bool *transition);
+static celix_status_t celix_dmComponent_calculateNewState(celix_dm_component_t *component, celix_dm_component_state_t currentState, celix_dm_component_state_t *newState);
+static celix_status_t celix_dmComponent_handleChange(celix_dm_component_t *component);
+static celix_status_t celix_dmComponent_handleAdd(celix_dm_component_t *component, const celix_dm_event_t* event);
+static celix_status_t celix_dmComponent_handleRemove(celix_dm_component_t *component, const celix_dm_event_t* event);
+static celix_status_t celix_dmComponent_handleSet(celix_dm_component_t *component, const celix_dm_event_t* event);
+static celix_status_t celix_dmComponent_disableDependencies(celix_dm_component_t *component);
+static celix_status_t celix_dmComponent_suspend(celix_dm_component_t *component, celix_dm_service_dependency_t *dependency);
+static celix_status_t celix_dmComponent_resume(celix_dm_component_t *component, celix_dm_service_dependency_t *dependency);
+static celix_status_t celix_dmComponent_disable(celix_dm_component_t *component);
+static bool celix_dmComponent_isDisabled(celix_dm_component_t *component);
+static void celix_dmComponent_cleanupRemovedDependencies(celix_dm_component_t* component);
 
 
 celix_dm_component_t* celix_dmComponent_create(bundle_context_t *context, const char* name) {
@@ -124,9 +134,10 @@ celix_dm_component_t* celix_dmComponent_createWithUUID(bundle_context_t *context
 
     component->providedInterfaces = celix_arrayList_create();
     component->dependencies = celix_arrayList_create();
+    component->removedDependencies = celix_arrayList_create();
     celixThreadMutex_create(&component->mutex, NULL);
     celixThreadCondition_init(&component->cond, NULL);
-    component->isStarted = false;
+    component->isEnabled = false;
     return component;
 }
 
@@ -145,28 +156,48 @@ void component_destroy(celix_dm_component_t *component) {
     celix_dmComponent_destroy(component);
 }
 
-static void celix_dmComponent_waitForNoAddRemOrSetDependencyInProgress(celix_dm_component_t* component, bool lockOnMutex) {
-    if (lockOnMutex) {
-        celixThreadMutex_lock(&component->mutex);
-    }
-    struct timespec start = celix_gettime(CLOCK_MONOTONIC);
-    while (component->nrOfSetAddRemCallsInProgress > 0) {
-        celixThreadCondition_timedwaitRelative(&component->cond, &component->mutex, 1, 0);
-        struct timespec now = celix_gettime(CLOCK_MONOTONIC);
-        if (celix_difftime(&start, &now) > 5) {
-            start = celix_gettime(CLOCK_MONOTONIC);
-            fw_log(component->context->framework->logger, CELIX_LOG_LEVEL_WARNING, "Add, remove or set dependency call still in progress for component %s (uuid=%s)", component->name, component->uuid);
+//static void celix_dmComponent_waitForNoAddRemOrSetDependencyInProgress(celix_dm_component_t* component, bool lockOnMutex) {
+//    if (lockOnMutex) {
+//        celixThreadMutex_lock(&component->mutex);
+//    }
+//    struct timespec start = celix_gettime(CLOCK_MONOTONIC);
+//    while (component->nrOfSvcDepependenciesInProgress > 0) {
+//        celixThreadCondition_timedwaitRelative(&component->cond, &component->mutex, 1, 0);
+//        struct timespec now = celix_gettime(CLOCK_MONOTONIC);
+//        if (celix_difftime(&start, &now) > 5) {
+//            start = celix_gettime(CLOCK_MONOTONIC);
+//            fw_log(component->context->framework->logger, CELIX_LOG_LEVEL_WARNING, "Add, remove or set dependency call still in progress or a stop service tracker is still in progress for component %s (uuid=%s)", component->name, component->uuid);
+//        }
+//    }
+//    if (lockOnMutex) {
+//        celixThreadMutex_unlock(&component->mutex);
+//    }
+//}
+
+void celix_dmComponent_destroy(celix_dm_component_t *component) {
+    if (component != NULL) {
+        celix_dmComponent_destroyAsync(component, NULL, NULL);
+        if (celix_framework_isCurrentThreadTheEventLoop(component->context->framework)) {
+            fw_log(component->context->framework->logger, CELIX_LOG_LEVEL_ERROR,
+                   "Cannot synchonized destroy dm component on Celix event thread. Use celix_dmComponent_destroyAsync instead!");
+        } else {
+            //TODO use done callback to sync (note that eventid is not enough, because another destroy event can be created.
+            celix_bundleContext_waitForEvents(component->context);
         }
     }
-    if (lockOnMutex) {
-        celixThreadMutex_unlock(&component->mutex);
-    }
 }
 
-void celix_dmComponent_destroy(celix_dm_component_t *component) {
-	if (component) {
-        celix_dmComponent_stop(component); //all service deregistered // all svc tracker stopped
+struct celix_dm_component_destroy_data {
+    celix_dm_component_t* cmp;
+    void* doneData;
+    void (*doneCallback)(void*);
+};
 
+static void celix_dmComponent_destroyCallback(void *voidData) {
+    struct celix_dm_component_destroy_data *data = voidData;
+    celix_dm_component_t *component = data->cmp;
+    celix_dmComponent_disable(component); //all service deregistered // all svc tracker stopped
+    if (celix_dmComponent_isDisabled(component)) {
         for (int i = 0; i < celix_arrayList_size(component->providedInterfaces); ++i) {
             dm_interface_t *interface = celix_arrayList_get(component->providedInterfaces, i);
 
@@ -178,18 +209,54 @@ void celix_dmComponent_destroy(celix_dm_component_t *component) {
         }
         celix_arrayList_destroy(component->providedInterfaces);
 
-
-        celix_dmComponent_waitForNoAddRemOrSetDependencyInProgress(component, true);
-
         for (int i = 0; i < celix_arrayList_size(component->dependencies); ++i) {
-            celix_dm_service_dependency_t* dep = celix_arrayList_get(component->dependencies, i);
-            celix_dmServiceDependency_destroy(dep);
+            celix_dm_service_dependency_t *dep = celix_arrayList_get(component->dependencies, i);
+            celix_dmServiceDependency_free(dep);
         }
         celix_arrayList_destroy(component->dependencies);
+
+        for (int i = 0; i < celix_arrayList_size(component->removedDependencies); ++i) {
+            celix_dm_service_dependency_t *dep = celix_arrayList_get(component->removedDependencies, i);
+            celix_dmServiceDependency_free(dep);
+        }
+        celix_arrayList_destroy(component->removedDependencies);
+
         celixThreadMutex_destroy(&component->mutex);
         celixThreadCondition_destroy(&component->cond);
-
         free(component);
+
+        if (data->doneCallback) {
+            data->doneCallback(data->doneData);
+        }
+        free(data);
+    } else {
+        //not yet disabled, adding a new event on the event queue
+        celix_bundle_t* bnd = celix_bundleContext_getBundle(component->context);
+        celix_framework_fireGenericEvent(
+                component->context->framework, -1, celix_bundle_getId(bnd),
+                "destroy dm component",
+                data,
+                celix_dmComponent_destroyCallback,
+                NULL,
+                NULL);
+    }
+}
+
+void celix_dmComponent_destroyAsync(celix_dm_component_t *component, void *doneData, void (*doneCallback)(void*)) {
+    if (component != NULL) {
+        struct celix_dm_component_destroy_data* data = malloc(sizeof(*data));
+        data->cmp = component;
+        data->doneData = doneData;
+        data->doneCallback = doneCallback;
+
+        celix_bundle_t* bnd = celix_bundleContext_getBundle(component->context);
+        celix_framework_fireGenericEvent(
+                component->context->framework, -1, celix_bundle_getId(bnd),
+                "destroy dm component",
+                data,
+                celix_dmComponent_destroyCallback,
+                NULL,
+                NULL);
 	}
 }
 
@@ -198,21 +265,21 @@ const char* celix_dmComponent_getUUID(celix_dm_component_t* cmp) {
     return cmp->uuid;
 }
 
-//call with lock
-static void celix_dmComponent_updateFilterOutOwnSvcDependencies(celix_dm_component_t* component) {
-    for (int i = 0; i < celix_arrayList_size(component->dependencies); ++i) {
-        celix_dm_service_dependency_t* dep = celix_arrayList_get(component->dependencies, i);
-        bool filterOut = false;
-        for (int k = 0; k < celix_arrayList_size(component->providedInterfaces); ++k) {
-            dm_interface_t* intf = celix_arrayList_get(component->providedInterfaces, k);
-            if (celix_utils_stringEquals(intf->serviceName, dep->serviceName)) {
-                filterOut = true;
-                break;
-            }
-        }
-        celix_dmServiceDependency_setFilterOutOwnSvcDependencies(dep, filterOut);
-    }
-}
+////call with lock
+//static void celix_dmComponent_updateFilterOutOwnSvcDependencies(celix_dm_component_t* component) {
+//    for (int i = 0; i < celix_arrayList_size(component->dependencies); ++i) {
+//        celix_dm_service_dependency_t* dep = celix_arrayList_get(component->dependencies, i);
+//        bool filterOut = false;
+//        for (int k = 0; k < celix_arrayList_size(component->providedInterfaces); ++k) {
+//            dm_interface_t* intf = celix_arrayList_get(component->providedInterfaces, k);
+//            if (celix_utils_stringEquals(intf->serviceName, dep->serviceName)) {
+//                filterOut = true;
+//                break;
+//            }
+//        }
+//        celix_dmServiceDependency_setFilterOutOwnSvcDependencies(dep, filterOut);
+//    }
+//}
 
 celix_status_t component_addServiceDependency(celix_dm_component_t *component, celix_dm_service_dependency_t *dep) {
     return celix_dmComponent_addServiceDependency(component, dep);
@@ -220,35 +287,37 @@ celix_status_t component_addServiceDependency(celix_dm_component_t *component, c
 
 celix_status_t celix_dmComponent_addServiceDependency(celix_dm_component_t *component, celix_dm_service_dependency_t *dep) {
     celix_status_t status = CELIX_SUCCESS;
-    celix_serviceDependency_setComponent(dep, component);
+    celix_dmServiceDependency_setComponent(dep, component);
 
     celixThreadMutex_lock(&component->mutex);
     arrayList_add(component->dependencies, dep);
     bool startDep = component->state != DM_CMP_STATE_INACTIVE;
     if (startDep) {
-        celix_serviceDependency_start(dep);
+        celix_dmServiceDependency_enable(dep);
     }
-    celix_dmComponent_updateFilterOutOwnSvcDependencies(component);
+    //celix_dmComponent_updateFilterOutOwnSvcDependencies(component);
+    celix_dmComponent_cleanupRemovedDependencies(component);
     celixThreadMutex_unlock(&component->mutex);
 
-    component_handleChange(component);
+    celix_dmComponent_handleChange(component);
     return status;
 }
 
 celix_status_t celix_dmComponent_removeServiceDependency(celix_dm_component_t *component, celix_dm_service_dependency_t *dep) {
 
     celixThreadMutex_lock(&component->mutex);
-    celix_dmComponent_waitForNoAddRemOrSetDependencyInProgress(component, false);
-    arrayList_removeElement(component->dependencies, dep);
-    bool stopDependency = component->state != DM_CMP_STATE_INACTIVE;
-    if (stopDependency) {
-        celix_serviceDependency_stop(dep);
-    }
-    celix_dmServiceDependency_destroy(dep);
-    celix_dmComponent_updateFilterOutOwnSvcDependencies(component);
+    //celix_dmComponent_waitForNoAddRemOrSetDependencyInProgress(component, false);
+    celix_arrayList_remove(component->dependencies, dep);
+    bool disableDependency = component->state != DM_CMP_STATE_INACTIVE;
+    if (disableDependency) {
+        celix_dmServiceDependency_disable(dep);
+    }
+    celix_arrayList_add(component->removedDependencies, dep);
+    //celix_dmComponent_updateFilterOutOwnSvcDependencies(component);
+    celix_dmComponent_cleanupRemovedDependencies(component);
     celixThreadMutex_unlock(&component->mutex);
 
-    component_handleChange(component);
+    celix_dmComponent_handleChange(component);
     return CELIX_SUCCESS;
 }
 
@@ -280,26 +349,72 @@ celix_status_t component_removeServiceDependency(celix_dm_component_t *component
     return celix_dmComponent_removeServiceDependency(component, dependency);
 }
 
-celix_status_t celix_private_dmComponent_start(celix_dm_component_t *component) {
+celix_status_t celix_private_dmComponent_enable(celix_dm_component_t *component) {
     celixThreadMutex_lock(&component->mutex);
-    if (!component->isStarted) {
-        component->isStarted = true;
+    if (!component->isEnabled) {
+        component->isEnabled = true;
     }
     celixThreadMutex_unlock(&component->mutex);
-    component_handleChange(component);
+    celix_dmComponent_handleChange(component);
     return CELIX_SUCCESS;
 }
 
-static celix_status_t celix_dmComponent_stop(celix_dm_component_t *component) {
+static celix_status_t celix_dmComponent_disable(celix_dm_component_t *component) {
     celixThreadMutex_lock(&component->mutex);
-    if (component->isStarted) {
-        component->isStarted = false;
+    if (component->isEnabled) {
+        component->isEnabled = false;
     }
     celixThreadMutex_unlock(&component->mutex);
-    component_handleChange(component);
+    celix_dmComponent_handleChange(component);
     return CELIX_SUCCESS;
 }
 
+static void celix_dmComponent_cleanupRemovedDependencies(celix_dm_component_t* component) {
+    //note should be called with lock
+    bool removedDep = true;
+    while (removedDep) {
+        removedDep = false;
+        for (int i = 0 ; i < celix_arrayList_size(component->removedDependencies); ++i) {
+            celix_dm_service_dependency_t* dep = celix_arrayList_get(component->removedDependencies, i);
+            if (celix_dmServiceDependency_isDisabled(dep)) {
+                celix_arrayList_remove(component->removedDependencies, dep);
+                celix_dmServiceDependency_destroy(dep);
+                removedDep = true;
+                break;
+            }
+        }
+    }
+}
+
+static bool celix_dmComponent_areAllDependenciesDisabled(celix_dm_component_t* component) {
+    //note should be called with lock
+    bool allDisabled = true;
+    for (int i = 0 ; allDisabled && i < celix_arrayList_size(component->dependencies); ++i) {
+        celix_dm_service_dependency_t* dep = celix_arrayList_get(component->dependencies, i);
+        if (!celix_dmServiceDependency_isDisabled(dep)) {
+            allDisabled = false;
+        }
+    }
+    for (int i = 0 ; allDisabled && i < celix_arrayList_size(component->removedDependencies); ++i) {
+        celix_dm_service_dependency_t* dep = celix_arrayList_get(component->removedDependencies, i);
+        if (!celix_dmServiceDependency_isDisabled(dep)) {
+            allDisabled = false;
+        }
+    }
+    return allDisabled;
+}
+
+static bool celix_dmComponent_isDisabled(celix_dm_component_t *component) {
+    bool isStopped;
+    celixThreadMutex_lock(&component->mutex);
+    isStopped =
+            !component->isEnabled &&
+            component->state == DM_CMP_STATE_INACTIVE &&
+            celix_dmComponent_areAllDependenciesDisabled(component);
+    celixThreadMutex_unlock(&component->mutex);
+    return isStopped;
+}
+
 
 celix_status_t component_setCLanguageProperty(celix_dm_component_t *component, bool setCLangProp) {
     return celix_dmComponent_setCLanguageProperty(component, setCLangProp);
@@ -342,7 +457,7 @@ celix_status_t celix_dmComponent_addInterface(celix_dm_component_t *component, c
         interface->svcId= -1L;
         celix_arrayList_add(component->providedInterfaces, interface);
         if (component->state == DM_CMP_STATE_TRACKING_OPTIONAL) {
-            component_registerServices(component);
+            celix_dmComponent_registerServices(component);
         }
         celixThreadMutex_unlock(&component->mutex);
     } else {
@@ -409,13 +524,13 @@ celix_status_t celix_private_dmComponent_handleEvent(celix_dm_component_t *compo
     celix_status_t status = CELIX_SUCCESS;
     switch (event->eventType) {
         case CELIX_DM_EVENT_SVC_ADD:
-            component_handleAdd(component, event);
+            celix_dmComponent_handleAdd(component, event);
             break;
         case CELIX_DM_EVENT_SVC_REM:
-            component_handleRemove(component, event);
+            celix_dmComponent_handleRemove(component, event);
             break;
         case CELIX_DM_EVENT_SVC_SET:
-            component_handleSet(component, event);
+            celix_dmComponent_handleSet(component, event);
             break;
         default:
             break;
@@ -423,34 +538,42 @@ celix_status_t celix_private_dmComponent_handleEvent(celix_dm_component_t *compo
     return status;
 }
 
-static celix_status_t component_suspend(celix_dm_component_t *component, celix_dm_service_dependency_t *dependency) {
+static celix_status_t celix_dmComponent_suspend(celix_dm_component_t *component, celix_dm_service_dependency_t *dependency) {
 	celix_status_t status = CELIX_SUCCESS;
 	dm_service_dependency_strategy_t strategy = celix_dmServiceDependency_getStrategy(dependency);
 	if (strategy == DM_SERVICE_DEPENDENCY_STRATEGY_SUSPEND &&  component->callbackStop != NULL) {
-	    component_unregisterServices(component);
+        fw_log(component->context->framework->logger, CELIX_LOG_LEVEL_TRACE,
+               "Suspending component %s (uuid=%s)",
+               component->name,
+               component->uuid);
+        celix_dmComponent_unregisterServices(component);
 		status = component->callbackStop(component->implementation);
 	}
 	return status;
 }
 
-static celix_status_t component_resume(celix_dm_component_t *component, celix_dm_service_dependency_t *dependency) {
+static celix_status_t celix_dmComponent_resume(celix_dm_component_t *component, celix_dm_service_dependency_t *dependency) {
 	celix_status_t status = CELIX_SUCCESS;
     dm_service_dependency_strategy_t strategy = celix_dmServiceDependency_getStrategy(dependency);
 	if (strategy == DM_SERVICE_DEPENDENCY_STRATEGY_SUSPEND &&  component->callbackStop != NULL) {
-        component_registerServices(component);
+        fw_log(component->context->framework->logger, CELIX_LOG_LEVEL_TRACE,
+               "Resuming component %s (uuid=%s)",
+               component->name,
+               component->uuid);
+        celix_dmComponent_registerServices(component);
 		status = component->callbackStart(component->implementation);
 	}
 	return status;
 }
 
-static celix_status_t component_handleEvent(celix_dm_component_t *component, const celix_dm_event_t* event, celix_status_t (*setAddOrRemFp)(celix_dm_service_dependency_t *dependency, void* svc, const celix_properties_t* props)) {
+static celix_status_t celix_dmComponent_handleEvent(celix_dm_component_t *component, const celix_dm_event_t* event, celix_status_t (*setAddOrRemFp)(celix_dm_service_dependency_t *dependency, void* svc, const celix_properties_t* props), const char *invokeName) {
     bool needSuspend = false;
     celixThreadMutex_lock(&component->mutex);
-    component->nrOfSetAddRemCallsInProgress += 1;
+    component->nrOfSvcDepependenciesInProgress += 1;
     celixThreadCondition_broadcast(&component->cond);
     switch (component->state) {
         case DM_CMP_STATE_TRACKING_OPTIONAL:
-            if (celix_serviceDependency_hasAddCallback(event->dep)) { //if to prevent unneeded suspends
+            if (celix_dmServiceDependency_hasAddCallback(event->dep)) { //if to prevent unneeded suspends
                 needSuspend = true;
             }
             break;
@@ -459,40 +582,46 @@ static celix_status_t component_handleEvent(celix_dm_component_t *component, con
     }
     celixThreadMutex_unlock(&component->mutex);
     if (needSuspend) {
-        component_suspend(component, event->dep);
-    }
+        celix_dmComponent_suspend(component, event->dep);
+    }
+    fw_log(component->context->framework->logger, CELIX_LOG_LEVEL_TRACE,
+        "Calling %s service for component %s (uuid=%s) on service dependency with type %s",
+        invokeName,
+        component->name,
+        component->uuid,
+        event->dep->serviceName);
     setAddOrRemFp(event->dep, event->svc, event->props);
     if (needSuspend) {
-        component_resume(component, event->dep);
+        celix_dmComponent_resume(component, event->dep);
     }
     celixThreadMutex_lock(&component->mutex);
-    component->nrOfSetAddRemCallsInProgress -= 1;
+    component->nrOfSvcDepependenciesInProgress -= 1;
     celixThreadCondition_broadcast(&component->cond);
     celixThreadMutex_unlock(&component->mutex);
-    component_handleChange(component);
+    celix_dmComponent_handleChange(component);
     return CELIX_SUCCESS;
 }
 
-static celix_status_t component_handleAdd(celix_dm_component_t *component, const celix_dm_event_t* event) {
-    return component_handleEvent(component, event, celix_serviceDependency_invokeAdd);
+static celix_status_t celix_dmComponent_handleAdd(celix_dm_component_t *component, const celix_dm_event_t* event) {
+    return celix_dmComponent_handleEvent(component, event, celix_dmServiceDependency_invokeAdd, "add");
 }
 
-static celix_status_t component_handleRemove(celix_dm_component_t *component, const celix_dm_event_t* event) {
-    return component_handleEvent(component, event, celix_serviceDependency_invokeRemove);
+static celix_status_t celix_dmComponent_handleRemove(celix_dm_component_t *component, const celix_dm_event_t* event) {
+    return celix_dmComponent_handleEvent(component, event, celix_dmServiceDependency_invokeRemove, "remove");
 }
 
-static celix_status_t component_handleSet(celix_dm_component_t *component, const celix_dm_event_t* event) {
-    return component_handleEvent(component, event, celix_serviceDependency_invokeSet);
+static celix_status_t celix_dmComponent_handleSet(celix_dm_component_t *component, const celix_dm_event_t* event) {
+    return celix_dmComponent_handleEvent(component, event, celix_dmServiceDependency_invokeSet, "set");
 }
 
 /**
  * perform state transition. This call should be called with the component->mutex locked.
  */
-static celix_status_t component_startDependencies(celix_dm_component_t *component) {
+static celix_status_t celix_dmComponent_disableDependencies(celix_dm_component_t *component) {
     for (int i = 0; i < celix_arrayList_size(component->dependencies); i++) {
         celix_dm_service_dependency_t *dependency = arrayList_get(component->dependencies, i);
         if (!celix_dmServiceDependency_isTrackerOpen(dependency)) {
-            celix_serviceDependency_start(dependency);
+            celix_dmServiceDependency_enable(dependency);
         }
     }
     return CELIX_SUCCESS;
@@ -501,13 +630,35 @@ static celix_status_t component_startDependencies(celix_dm_component_t *componen
 /**
  * perform state transition. This call should be called with the component->mutex locked.
  */
-static celix_status_t component_stopDependencies(celix_dm_component_t *component) {
+static celix_status_t celix_dmComponent_enableDependencies(celix_dm_component_t *component) {
+
+    celix_array_list_t* depsToStop = NULL;
+
     for (int i = 0; i < celix_arrayList_size(component->dependencies); i++) {
         celix_dm_service_dependency_t *dependency = arrayList_get(component->dependencies, i);
         if (celix_dmServiceDependency_isTrackerOpen(dependency)) {
-            celix_serviceDependency_stop(dependency);
+            if (depsToStop == NULL) {
+                depsToStop = celix_arrayList_create();
+            }
+            celix_arrayList_add(depsToStop, dependency);
+            component->nrOfSvcDepependenciesInProgress += 1;
+            celixThreadCondition_broadcast(&component->cond);
         }
     }
+
+    if (depsToStop != NULL) {
+        celixThreadMutex_unlock(&component->mutex);
+        for (int i = 0; i < celix_arrayList_size(depsToStop); ++i) {
+            celix_dm_service_dependency_t *dependency = arrayList_get(depsToStop, i);
+            celix_dmServiceDependency_disable(dependency);
+        }
+        celixThreadMutex_lock(&component->mutex);
+
+        component->nrOfSvcDepependenciesInProgress -= celix_arrayList_size(depsToStop);
+        celixThreadCondition_broadcast(&component->cond);
+        celix_arrayList_destroy(depsToStop);
+    }
+
     return CELIX_SUCCESS;
 }
 
@@ -515,7 +666,7 @@ static celix_status_t component_stopDependencies(celix_dm_component_t *component
 /**
  * Calculate and handle state change. This call should be called with the component->mutex locked.
  */
-static void component_handleChangeOnEventThread(void *data) {
+static void celix_dmComponent_handleChangeOnEventThread(void *data) {
     celix_dm_component_t* component = data;
     assert(celix_framework_isCurrentThreadTheEventLoop(component->context->framework));
 
@@ -525,9 +676,9 @@ static void component_handleChangeOnEventThread(void *data) {
     bool transition = false;
     do {
         oldState = component->state;
-        celix_status_t status = component_calculateNewState(component, oldState, &newState);
+        celix_status_t status = celix_dmComponent_calculateNewState(component, oldState, &newState);
         if (status == CELIX_SUCCESS) {
-            status = component_performTransition(component, oldState, newState, &transition);
+            status = celix_dmComponent_performTransition(component, oldState, newState, &transition);
             component->state = newState;
         }
 
@@ -538,9 +689,9 @@ static void component_handleChangeOnEventThread(void *data) {
     celixThreadMutex_unlock(&component->mutex);
 }
 
-static celix_status_t component_handleChange(celix_dm_component_t *component) {
+static celix_status_t celix_dmComponent_handleChange(celix_dm_component_t *component) {
     if (celix_framework_isCurrentThreadTheEventLoop(component->context->framework)) {
-        component_handleChangeOnEventThread(component);
+        celix_dmComponent_handleChangeOnEventThread(component);
     } else {
         long eventId = celix_framework_fireGenericEvent(
                 component->context->framework,
@@ -548,7 +699,7 @@ static celix_status_t component_handleChange(celix_dm_component_t *component) {
                 celix_bundle_getId(component->context->bundle),
                 "dm component handle change",
                 component,
-                component_handleChangeOnEventThread,
+                celix_dmComponent_handleChangeOnEventThread,
                 NULL,
                 NULL);
         celix_framework_waitForGenericEvent(component->context->framework, eventId);
@@ -556,38 +707,21 @@ static celix_status_t component_handleChange(celix_dm_component_t *component) {
     return CELIX_SUCCESS;
 }
 
-
-///**
-// * Check if service trackers are still open for the dependencies.
-// * This call should be called with the component->mutex locked.
-// */
-//static bool component_allDependencyStopped(celix_dm_component_t* component) {
-//    bool anyOpen = false;
-//    for (int i = 0; i < celix_arrayList_size(component->dependencies); ++i) {
-//        celix_dm_service_dependency_t *dep = celix_arrayList_get(component->dependencies, i);
-//        if (celix_dmServiceDependency_isTrackerOpen(dep)) {
-//            anyOpen = true;
-//            break;
-//        }
-//    }
-//    return !anyOpen;
-//}
-
 /**
  * Calculate possible state change. This call should be called with the component->mutex locked.
  */
-static celix_status_t component_calculateNewState(celix_dm_component_t *component, celix_dm_component_state_t currentState, celix_dm_component_state_t *newState) {
+static celix_status_t celix_dmComponent_calculateNewState(celix_dm_component_t *component, celix_dm_component_state_t currentState, celix_dm_component_state_t *newState) {
     celix_status_t status = CELIX_SUCCESS;
 
-    bool allResolved = component_areAllRequiredServiceDependenciesResolved(component);
+    bool allResolved = celix_dmComponent_areAllRequiredServiceDependenciesResolved(component);
     if (currentState == DM_CMP_STATE_INACTIVE) {
-        if (component->isStarted) {
+        if (component->isEnabled) {
             *newState = DM_CMP_STATE_WAITING_FOR_REQUIRED;
         } else {
             *newState = currentState;
         }
     } else if (currentState == DM_CMP_STATE_WAITING_FOR_REQUIRED) {
-        if (!component->isStarted) {
+        if (!component->isEnabled) {
             *newState = DM_CMP_STATE_INACTIVE;
         } else {
             if (allResolved) {
@@ -597,7 +731,7 @@ static celix_status_t component_calculateNewState(celix_dm_component_t *componen
             }
         }
     } else if (currentState == DM_CMP_STATE_INSTANTIATED_AND_WAITING_FOR_REQUIRED) {
-        if (!component->isStarted) {
+        if (!component->isEnabled) {
             *newState = DM_CMP_STATE_WAITING_FOR_REQUIRED;
         } else {
             if (allResolved) {
@@ -607,7 +741,7 @@ static celix_status_t component_calculateNewState(celix_dm_component_t *componen
             }
         }
     } else if (currentState == DM_CMP_STATE_TRACKING_OPTIONAL) {
-        if (component->isStarted && allResolved) {
+        if (component->isEnabled && allResolved) {
             *newState = currentState;
         } else {
             *newState = DM_CMP_STATE_INSTANTIATED_AND_WAITING_FOR_REQUIRED;
@@ -624,14 +758,23 @@ static celix_status_t component_calculateNewState(celix_dm_component_t *componen
 /**
  * perform state transition. This call should be called with the component->mutex locked.
  */
-static celix_status_t component_performTransition(celix_dm_component_t *component, celix_dm_component_state_t oldState, celix_dm_component_state_t newState, bool *transition) {
-    celix_status_t status = CELIX_SUCCESS;
-    fw_log(component->context->framework->logger, CELIX_LOG_LEVEL_TRACE, "performing transition for component %s from state %i to state %i\n", component->name, oldState, newState);
-
+static celix_status_t celix_dmComponent_performTransition(celix_dm_component_t *component, celix_dm_component_state_t oldState, celix_dm_component_state_t newState, bool *transition) {
     if (oldState == newState) {
         *transition = false;
-    } else if (oldState == DM_CMP_STATE_INACTIVE && newState == DM_CMP_STATE_WAITING_FOR_REQUIRED) {
-        component_startDependencies(component);
+        return CELIX_SUCCESS;
+    }
+
+    fw_log(component->context->framework->logger,
+           CELIX_LOG_LEVEL_TRACE,
+           "performing transition for component '%s' (uuid=%s) from state %s to state %s",
+           component->name,
+           component->uuid,
+           celix_dmComponent_stateToString(oldState),
+           celix_dmComponent_stateToString(newState));
+
+    celix_status_t status = CELIX_SUCCESS;
+    if (oldState == DM_CMP_STATE_INACTIVE && newState == DM_CMP_STATE_WAITING_FOR_REQUIRED) {
+        celix_dmComponent_disableDependencies(component);
         *transition = true;
     } else if (oldState == DM_CMP_STATE_WAITING_FOR_REQUIRED && newState == DM_CMP_STATE_INSTANTIATED_AND_WAITING_FOR_REQUIRED) {
         if (component->callbackInit) {
@@ -642,10 +785,10 @@ static celix_status_t component_performTransition(celix_dm_component_t *componen
         if (component->callbackStart) {
         	status = component->callbackStart(component->implementation);
         }
-        component_registerServices(component);
+        celix_dmComponent_registerServices(component);
         *transition = true;
     } else if (oldState == DM_CMP_STATE_TRACKING_OPTIONAL && newState == DM_CMP_STATE_INSTANTIATED_AND_WAITING_FOR_REQUIRED) {
-        component_unregisterServices(component);
+        celix_dmComponent_unregisterServices(component);
         if (component->callbackStop) {
         	status = component->callbackStop(component->implementation);
         }
@@ -656,7 +799,7 @@ static celix_status_t component_performTransition(celix_dm_component_t *componen
         }
         *transition = true;
     } else if (oldState == DM_CMP_STATE_WAITING_FOR_REQUIRED && newState == DM_CMP_STATE_INACTIVE) {
-        component_stopDependencies(component);
+        celix_dmComponent_enableDependencies(component);
         *transition = true;
     }
 
@@ -666,13 +809,13 @@ static celix_status_t component_performTransition(celix_dm_component_t *componen
 /**
  * Check if all required dependencies are resolved. This call should be called with the component->mutex locked.
  */
-static bool component_areAllRequiredServiceDependenciesResolved(celix_dm_component_t *component) {
+static bool celix_dmComponent_areAllRequiredServiceDependenciesResolved(celix_dm_component_t *component) {
     bool allResolved = true;
     for (int i = 0; i < celix_arrayList_size(component->dependencies); i++) {
         celix_dm_service_dependency_t *dependency = celix_arrayList_get(component->dependencies, i);
         bool started = celix_dmServiceDependency_isTrackerOpen(dependency);
         bool required = celix_dmServiceDependency_isRequired(dependency);
-        bool available = celix_serviceDependency_isAvailable(dependency);
+        bool available = celix_dmServiceDependency_isAvailable(dependency);
         if (!started) {
             allResolved = false;
             break;
@@ -688,7 +831,7 @@ static bool component_areAllRequiredServiceDependenciesResolved(celix_dm_compone
 /**
  * Register component services (if not already registered). This call should be called with the component->mutex locked.
  */
-static celix_status_t component_registerServices(celix_dm_component_t *component) {
+static celix_status_t celix_dmComponent_registerServices(celix_dm_component_t *component) {
     for (int i = 0; i < celix_arrayList_size(component->providedInterfaces); i++) {
         dm_interface_t *interface = arrayList_get(component->providedInterfaces, i);
         if (interface->svcId == -1L) {
@@ -698,6 +841,11 @@ static celix_status_t component_registerServices(celix_dm_component_t *component
             opts.svc = (void*)interface->service;
             opts.serviceName = interface->serviceName;
             opts.serviceLanguage = celix_properties_get(regProps, CELIX_FRAMEWORK_SERVICE_LANGUAGE, NULL);
+            fw_log(component->context->framework->logger, CELIX_LOG_LEVEL_TRACE,
+                   "Async registering service %s for component %s (uuid=%s)",
+                   interface->serviceName,
+                   component->name,
+                   component->uuid);
             interface->svcId = celix_bundleContext_registerServiceWithOptionsAsync(component->context, &opts);
             if (!celix_framework_isCurrentThreadTheEventLoop(component->context->framework)) {
                 celix_framework_waitForAsyncRegistration(component->context->framework, interface->svcId);
@@ -711,23 +859,33 @@ static celix_status_t component_registerServices(celix_dm_component_t *component
 /**
  * Unregister component services. This call should be called with the component->mutex locked.
  */
-static celix_status_t component_unregisterServices(celix_dm_component_t *component) {
+static celix_status_t celix_dmComponent_unregisterServices(celix_dm_component_t *component) {
     celix_status_t status = CELIX_SUCCESS;
 
-    celix_array_list_t* ids = celix_arrayList_create();
+    celix_array_list_t* ids = NULL;
     for (int i = 0; i < celix_arrayList_size(component->providedInterfaces); ++i) {
 	    dm_interface_t *interface = arrayList_get(component->providedInterfaces, i);
+	    if (ids == NULL) {
+            ids = celix_arrayList_create();
+	    }
 	    celix_arrayList_addLong(ids, interface->svcId);
 	    interface->svcId = -1L;
+        fw_log(component->context->framework->logger, CELIX_LOG_LEVEL_TRACE,
+               "Unregistering service %s for component %s (uuid=%s)",
+               interface->serviceName,
+               component->name,
+               component->uuid);
     }
 
-    celixThreadMutex_unlock(&component->mutex);
-    for (int i = 0; i < celix_arrayList_size(ids); ++i) {
-        long svcId = celix_arrayList_getLong(ids, i);
-        celix_bundleContext_unregisterService(component->context, svcId);
+    if (ids != NULL) {
+        celixThreadMutex_unlock(&component->mutex);
+        for (int i = 0; i < celix_arrayList_size(ids); ++i) {
+            long svcId = celix_arrayList_getLong(ids, i);
+            celix_bundleContext_unregisterService(component->context, svcId);
+        }
+        celix_arrayList_destroy(ids);
+        celixThreadMutex_lock(&component->mutex);
     }
-    celixThreadMutex_lock(&component->mutex);
-    celix_arrayList_destroy(ids);
 
     return status;
 }
@@ -848,3 +1006,16 @@ bool celix_dmComponent_isActive(celix_dm_component_t *component) {
     celixThreadMutex_unlock(&component->mutex);
     return active;
 }
+
+const char* celix_dmComponent_stateToString(celix_dm_component_state_t state) {
+    switch(state) {
+        case DM_CMP_STATE_INACTIVE:
+            return "DM_CMP_STATE_INACTIVE";
+        case DM_CMP_STATE_WAITING_FOR_REQUIRED:
+            return "DM_CMP_STATE_WAITING_FOR_REQUIRED";
+        case DM_CMP_STATE_INSTANTIATED_AND_WAITING_FOR_REQUIRED:
+            return "DM_CMP_STATE_INSTANTIATED_AND_WAITING_FOR_REQUIRED";
+        default: //only DM_CMP_STATE_TRACKING_OPTIONAL left
+            return "DM_CMP_STATE_TRACKING_OPTIONAL";
+    }
+}
diff --git a/libs/framework/src/dm_component_impl.h b/libs/framework/src/dm_component_impl.h
index 452f89f..83485f3 100644
--- a/libs/framework/src/dm_component_impl.h
+++ b/libs/framework/src/dm_component_impl.h
@@ -35,7 +35,7 @@ extern "C" {
 #include "dm_service_dependency_impl.h"
 #include "celix_dm_event.h"
 
-celix_status_t celix_private_dmComponent_start(celix_dm_component_t *component);
+celix_status_t celix_private_dmComponent_enable(celix_dm_component_t *component);
 celix_status_t celix_private_dmComponent_handleEvent(celix_dm_component_t *component, const celix_dm_event_t* event);
 
 #ifdef __cplusplus
diff --git a/libs/framework/src/dm_dependency_manager_impl.c b/libs/framework/src/dm_dependency_manager_impl.c
index 5073072..7725491 100644
--- a/libs/framework/src/dm_dependency_manager_impl.c
+++ b/libs/framework/src/dm_dependency_manager_impl.c
@@ -28,7 +28,8 @@
 #include "celix_dependency_manager.h"
 #include "celix_bundle.h"
 #include "celix_framework.h"
-
+#include "bundle_context_private.h"
+#include "framework_private.h"
 
 celix_dependency_manager_t* celix_private_dependencyManager_create(celix_bundle_context_t *context) {
 	celix_dependency_manager_t *manager = calloc(1, sizeof(*manager));
@@ -59,32 +60,38 @@ celix_status_t celix_dependencyManager_add(celix_dependency_manager_t *manager,
 	celix_arrayList_add(manager->components, component);
     celixThreadMutex_unlock(&manager->mutex);
 
-	status = celix_private_dmComponent_start(component);
+	status = celix_private_dmComponent_enable(component);
 	return status;
 }
 
-
-celix_status_t celix_dependencyManager_remove(celix_dependency_manager_t *manager, celix_dm_component_t *component) {
-	celix_status_t status;
-
-	celix_array_list_entry_t entry;
-	memset(&entry, 0, sizeof(entry));
-	entry.voidPtrVal = component;
+celix_status_t celix_dependencyManager_removeWithoutDestroy(celix_dependency_manager_t *manager, celix_dm_component_t *component) {
+    celix_status_t status;
 
     celixThreadMutex_lock(&manager->mutex);
-	int index = celix_arrayList_indexOf(manager->components, entry);
+    bool found = false;
+    for (int i = 0; i < celix_arrayList_size(manager->components); ++i) {
+        celix_dm_component_t* visit = celix_arrayList_get(manager->components, i);
+        if (visit == component) {
+            celix_arrayList_removeAt(manager->components, i);
+            found = true;
+            break;
+        }
+    }
+    celixThreadMutex_unlock(&manager->mutex);
 
-	if (index >= 0) {
-        celix_arrayList_removeAt(manager->components, index);
-        celixThreadMutex_unlock(&manager->mutex);
-        celix_dmComponent_destroy(component);
-	} else {
-        celixThreadMutex_unlock(&manager->mutex);
-	    fprintf(stderr, "Cannot find component with pointer %p\n", component);
-	    status = CELIX_BUNDLE_EXCEPTION;
-	}
+    if (!found) {
+        fw_log(manager->ctx->framework->logger, CELIX_LOG_LEVEL_ERROR, "Cannot find component %s (uuid=%s)",
+            celix_dmComponent_getName(component),
+            celix_dmComponent_getUUID(component));
+        status = CELIX_BUNDLE_EXCEPTION;
+    }
 
+    return status;
+}
 
+celix_status_t celix_dependencyManager_remove(celix_dependency_manager_t *manager, celix_dm_component_t *component) {
+    celix_status_t  status = celix_dependencyManager_removeWithoutDestroy(manager, component);
+	celix_dmComponent_destroy(component);
 	return status;
 }
 
diff --git a/libs/framework/src/dm_service_dependency.c b/libs/framework/src/dm_service_dependency.c
index 80bf71a..ebaf76b 100644
--- a/libs/framework/src/dm_service_dependency.c
+++ b/libs/framework/src/dm_service_dependency.c
@@ -19,6 +19,8 @@
 
 #include <stdlib.h>
 #include <string.h>
+#include <assert.h>
+#include <celix_bundle.h>
 
 #include "celix_constants.h"
 #include "celix_utils.h"
@@ -48,6 +50,8 @@ celix_status_t serviceDependency_create(celix_dm_service_dependency_t **dependen
 celix_dm_service_dependency_t* celix_dmServiceDependency_create() {
 	celix_dm_service_dependency_t *dep = calloc(1, sizeof(*dep));
 	dep->strategy = DM_SERVICE_DEPENDENCY_DEFAULT_STRATEGY;
+	dep->svcTrackerId = -1;
+	celixThreadMutex_create(&dep->mutex, NULL);
     return dep;
 }
 
@@ -58,16 +62,81 @@ celix_status_t serviceDependency_destroy(celix_dm_service_dependency_t **depende
 	return CELIX_SUCCESS;
 }
 
-void celix_dmServiceDependency_destroy(celix_dm_service_dependency_t *dep) {
-	if (dep != NULL) {
-        celix_bundle_context_t* ctx = celix_dmComponent_getBundleContext(dep->component);
-        celix_bundleContext_waitForAsyncStopTracker(ctx, dep->svcTrackerId);
+void celix_dmServiceDependency_free(celix_dm_service_dependency_t* dep) {
+    if (dep != NULL) {
         celixThreadMutex_destroy(&dep->mutex);
         free(dep->serviceName);
         free(dep->versionRange);
         free(dep->filter);
-		free(dep);
-	}
+        free(dep);
+    }
+}
+
+void celix_dmServiceDependency_destroy(celix_dm_service_dependency_t *dep) {
+    if (dep != NULL && dep->component != NULL) {
+        celix_bundle_context_t *ctx = celix_dmComponent_getBundleContext(dep->component);
+        celix_dmServiceDependency_destroyAsync(dep, NULL, NULL);
+        if (celix_framework_isCurrentThreadTheEventLoop(ctx->framework)) {
+            fw_log(ctx->framework->logger, CELIX_LOG_LEVEL_ERROR,
+                   "Cannot synchonized destroy dm service dependency on Celix event thread. Use celix_dmServiceDependency_destroyAsync instead!");
+        } else {
+            //TODO use done callback to sync (note that eventid is not enough, because another destroy event can be created.
+            celix_bundleContext_waitForEvents(ctx);
+        }
+    } else {
+        celix_dmServiceDependency_free(dep);
+    }
+}
+
+
+
+struct celix_dm_service_dependency_destroy_data {
+    celix_dm_service_dependency_t* dep;
+    void* doneData;
+    void (*doneCallback)(void*);
+};
+
+static void celix_dmServiceDependency_destroyCallback(void *voidData) {
+    struct celix_dm_service_dependency_destroy_data* data = voidData;
+
+    celix_dmServiceDependency_disable(data->dep);
+    if (data->dep->component == NULL || celix_dmServiceDependency_isDisabled(data->dep)) {
+        celix_dmServiceDependency_free(data->dep);
+        if (data->doneCallback) {
+            data->doneCallback(data->doneData);
+        }
+        free(data);
+    } else {
+        celix_bundle_context_t* ctx = celix_dmComponent_getBundleContext(data->dep->component);
+        celix_bundle_t* bnd = celix_bundleContext_getBundle(ctx);
+        celix_framework_fireGenericEvent(
+                ctx->framework, -1, celix_bundle_getId(bnd),
+                "destroy dm service dependency",
+                data,
+                celix_dmServiceDependency_destroyCallback,
+                NULL,
+                NULL);
+    }
+}
+
+void celix_dmServiceDependency_destroyAsync(celix_dm_service_dependency_t *dep, void *doneData, void (*doneCallback)(void*)) {
+    if (dep != NULL && dep->component != NULL) {
+        celix_bundle_context_t* ctx = celix_dmComponent_getBundleContext(dep->component);
+        celix_bundle_t* bnd = celix_bundleContext_getBundle(ctx);
+        struct celix_dm_service_dependency_destroy_data* data = malloc(sizeof(*data));
+        data->dep = dep;
+        data->doneData = doneData;
+        data->doneCallback = doneCallback;
+        celix_framework_fireGenericEvent(
+                ctx->framework, -1, celix_bundle_getId(bnd),
+                "destroy dm service dependency",
+                data,
+                celix_dmServiceDependency_destroyCallback,
+                NULL,
+                NULL);
+    } else if (dep != NULL) {
+        celix_dmServiceDependency_free(dep);
+    }
 }
 
 celix_status_t serviceDependency_setRequired(celix_dm_service_dependency_t *dependency, bool required) {
@@ -180,12 +249,12 @@ celix_status_t celix_dmServiceDependency_setCallbacksWithOptions(celix_dm_servic
 	return CELIX_SUCCESS;
 }
 
-celix_status_t celix_serviceDependency_setComponent(celix_dm_service_dependency_t *dependency, celix_dm_component_t *component) {
+celix_status_t celix_dmServiceDependency_setComponent(celix_dm_service_dependency_t *dependency, celix_dm_component_t *component) {
     dependency->component = component;
 	return CELIX_SUCCESS;
 }
 
-celix_status_t celix_serviceDependency_start(celix_dm_service_dependency_t *dependency) {
+celix_status_t celix_dmServiceDependency_enable(celix_dm_service_dependency_t *dependency) {
     celix_bundle_context_t* ctx = celix_dmComponent_getBundleContext(dependency->component);
 
     if (dependency->serviceName == NULL && dependency->filter == NULL) {
@@ -195,8 +264,7 @@ celix_status_t celix_serviceDependency_start(celix_dm_service_dependency_t *depe
     }
 
     celixThreadMutex_lock(&dependency->mutex);
-    if (!dependency->isTrackerOpen) {
-        dependency->isTrackerOpen = true;
+    if (dependency->svcTrackerId == -1L) {
         celix_service_tracking_options_t opts = CELIX_EMPTY_SERVICE_TRACKING_OPTIONS;
         opts.filter.filter = dependency->filter;
         opts.filter.serviceName = dependency->serviceName;
@@ -218,31 +286,48 @@ celix_status_t celix_serviceDependency_start(celix_dm_service_dependency_t *depe
 	return CELIX_SUCCESS;
 }
 
-celix_status_t celix_serviceDependency_stop(celix_dm_service_dependency_t *dependency) {
-    celix_bundle_context_t* ctx = celix_dmComponent_getBundleContext(dependency->component);
+static void celix_serviceDependency_stopCallback(void *data) {
+    celix_dm_service_dependency_t* dependency = data;
+    celixThreadMutex_lock(&dependency->mutex);
+    dependency->nrOfActiveStoppingTrackers -= 1;
+    celixThreadMutex_unlock(&dependency->mutex);
+}
 
+celix_status_t celix_dmServiceDependency_disable(celix_dm_service_dependency_t *dependency) {
     celixThreadMutex_lock(&dependency->mutex);
-    bool open = dependency->isTrackerOpen;
-    dependency->isTrackerOpen = false;
-    if (open && dependency->svcTrackerId >= 0) {
-        celix_bundleContext_stopTrackerAsync(ctx, dependency->svcTrackerId, NULL, NULL);
+    if (dependency->svcTrackerId >= 0) {
+        celix_bundle_context_t* ctx = celix_dmComponent_getBundleContext(dependency->component);
+        celix_bundleContext_stopTrackerAsync(ctx, dependency->svcTrackerId, dependency, celix_serviceDependency_stopCallback);
+        dependency->svcTrackerId = -1;
+        dependency->nrOfActiveStoppingTrackers += 1;
     }
     celixThreadMutex_unlock(&dependency->mutex);
 
 	return CELIX_SUCCESS;
 }
 
+bool celix_dmServiceDependency_isDisabled(celix_dm_service_dependency_t *dependency) {
+    bool isStopped;
+    celixThreadMutex_lock(&dependency->mutex);
+    isStopped = dependency->svcTrackerId == -1L && dependency->nrOfActiveStoppingTrackers == 0;
+    celixThreadMutex_unlock(&dependency->mutex);
+    return isStopped;
+}
+
 /**
  * checks whether the service dependency needs to be ignore. This can be needed if a component depends on the same service types as it provides
  */
 static bool serviceDependency_ignoreSvcCallback(celix_dm_service_dependency_t* dependency, const celix_properties_t* props) {
+    return false;
+    /* TODO still needed
    bool filterOut = celix_dmServiceDependency_filterOutOwnSvcDependencies(dependency);
    if (filterOut) {
        const char *uuid = celix_dmComponent_getUUID(dependency->component);
        const char *svcCmpUUID = celix_properties_get(props, CELIX_DM_COMPONENT_UUID, NULL);
-       return svcCmpUUID != NULL && celix_utils_stringEquals(uuid, svcCmpUUID);
+       bool ignore = svcCmpUUID != NULL && celix_utils_stringEquals(uuid, svcCmpUUID);
+       return ignore;
    }
-   return false;
+   return false;*/
 }
 
 static void serviceDependency_setServiceTrackerCallback(void *handle, void *svc, const celix_properties_t *props) {
@@ -260,7 +345,7 @@ static void serviceDependency_setServiceTrackerCallback(void *handle, void *svc,
     celix_private_dmComponent_handleEvent(dependency->component, &event);
 }
 
-celix_status_t celix_serviceDependency_invokeSet(celix_dm_service_dependency_t *dependency, void* svc, const celix_properties_t* props) {
+celix_status_t celix_dmServiceDependency_invokeSet(celix_dm_service_dependency_t *dependency, void* svc, const celix_properties_t* props) {
     if (dependency->set) {
         dependency->set(serviceDependency_getCallbackHandle(dependency), svc);
     }
@@ -289,7 +374,7 @@ static void serviceDependency_addServiceTrackerCallback(void *handle, void *svc,
     celix_private_dmComponent_handleEvent(dependency->component, &event);
 }
 
-celix_status_t celix_serviceDependency_invokeAdd(celix_dm_service_dependency_t *dependency, void* svc, const celix_properties_t* props) {
+celix_status_t celix_dmServiceDependency_invokeAdd(celix_dm_service_dependency_t *dependency, void* svc, const celix_properties_t* props) {
     void *handle = serviceDependency_getCallbackHandle(dependency);
     if (dependency->add) {
         dependency->add(handle, svc);
@@ -319,7 +404,7 @@ static void serviceDependency_removeServiceTrackerCallback(void *handle, void *s
     celix_private_dmComponent_handleEvent(dependency->component, &event);
 }
 
-celix_status_t celix_serviceDependency_invokeRemove(celix_dm_service_dependency_t *dependency, void* svc, const celix_properties_t* props) {
+celix_status_t celix_dmServiceDependency_invokeRemove(celix_dm_service_dependency_t *dependency, void* svc, const celix_properties_t* props) {
     if (dependency->remove) {
         dependency->remove(serviceDependency_getCallbackHandle(dependency), svc);
     }
@@ -329,19 +414,19 @@ celix_status_t celix_serviceDependency_invokeRemove(celix_dm_service_dependency_
     return CELIX_SUCCESS;
 }
 
-bool celix_serviceDependency_hasSetCallback(const celix_dm_service_dependency_t *dependency) {
+bool celix_dmServiceDependency_hasSetCallback(const celix_dm_service_dependency_t *dependency) {
     return dependency->set != NULL || dependency->setWithProperties != NULL;
 }
 
-bool celix_serviceDependency_hasAddCallback(const celix_dm_service_dependency_t *dependency) {
+bool celix_dmServiceDependency_hasAddCallback(const celix_dm_service_dependency_t *dependency) {
     return dependency->add != NULL || dependency->addWithProperties != NULL;
 }
 
-bool celix_serviceDependency_hasRemoveCallback(const celix_dm_service_dependency_t *dependency) {
+bool celix_dmServiceDependency_hasRemoveCallback(const celix_dm_service_dependency_t *dependency) {
     return dependency->remove != NULL || dependency->remWithProperties != NULL;
 }
 
-bool celix_serviceDependency_isAvailable(celix_dm_service_dependency_t *dependency) {
+bool celix_dmServiceDependency_isAvailable(celix_dm_service_dependency_t *dependency) {
     bool avail;
     celixThreadMutex_lock(&dependency->mutex);
     avail = dependency->trackedSvcCount > 0;
@@ -355,9 +440,9 @@ bool celix_dmServiceDependency_isRequired(const celix_dm_service_dependency_t* d
 
 bool celix_dmServiceDependency_isTrackerOpen(celix_dm_service_dependency_t* dependency) {
     celixThreadMutex_lock(&dependency->mutex);
-    bool started = dependency->isTrackerOpen;
+    bool isOpen = dependency->svcTrackerId >= 0;
     celixThreadMutex_unlock(&dependency->mutex);
-    return started;
+    return isOpen;
 }
 
 bool celix_dmServiceDependency_filterOutOwnSvcDependencies(celix_dm_service_dependency_t* dependency) {
diff --git a/libs/framework/src/dm_service_dependency_impl.h b/libs/framework/src/dm_service_dependency_impl.h
index df48b22..cafa910 100644
--- a/libs/framework/src/dm_service_dependency_impl.h
+++ b/libs/framework/src/dm_service_dependency_impl.h
@@ -57,8 +57,8 @@ struct celix_dm_service_dependency {
     celix_dm_component_t *component;
 
     celix_thread_mutex_t mutex; //protects below
-    long svcTrackerId;
-    bool isTrackerOpen;
+    long svcTrackerId; //active tracker id
+    size_t nrOfActiveStoppingTrackers; //nr of async stop tracker still active (should be 0 or 1)
     size_t trackedSvcCount;
     void* callbackHandle; //This handle can be set to be used instead of the component implementation
 
@@ -71,20 +71,22 @@ struct celix_dm_service_dependency {
     bool filterOutOwnSvcDependencies;
 };
 
-celix_status_t celix_serviceDependency_start(celix_dm_service_dependency_t *dependency);
-celix_status_t celix_serviceDependency_stop(celix_dm_service_dependency_t *dependency);
+celix_status_t celix_dmServiceDependency_enable(celix_dm_service_dependency_t *dependency);
+celix_status_t celix_dmServiceDependency_disable(celix_dm_service_dependency_t *dependency);
 
-celix_status_t celix_serviceDependency_setComponent(celix_dm_service_dependency_t *dependency, celix_dm_component_t *component);
+bool celix_dmServiceDependency_isDisabled(celix_dm_service_dependency_t *dependency);
 
-celix_status_t celix_serviceDependency_invokeSet(celix_dm_service_dependency_t *dependency, void* svc, const celix_properties_t* props);
-celix_status_t celix_serviceDependency_invokeAdd(celix_dm_service_dependency_t *dependency, void* svc, const celix_properties_t* props);
-celix_status_t celix_serviceDependency_invokeRemove(celix_dm_service_dependency_t *dependency, void* svc, const celix_properties_t* props);
+celix_status_t celix_dmServiceDependency_setComponent(celix_dm_service_dependency_t *dependency, celix_dm_component_t *component);
 
-bool celix_serviceDependency_hasSetCallback(const celix_dm_service_dependency_t *dependency);
-bool celix_serviceDependency_hasAddCallback(const celix_dm_service_dependency_t *dependency);
-bool celix_serviceDependency_hasRemoveCallback(const celix_dm_service_dependency_t *dependency);
+celix_status_t celix_dmServiceDependency_invokeSet(celix_dm_service_dependency_t *dependency, void* svc, const celix_properties_t* props);
+celix_status_t celix_dmServiceDependency_invokeAdd(celix_dm_service_dependency_t *dependency, void* svc, const celix_properties_t* props);
+celix_status_t celix_dmServiceDependency_invokeRemove(celix_dm_service_dependency_t *dependency, void* svc, const celix_properties_t* props);
 
-bool celix_serviceDependency_isAvailable(celix_dm_service_dependency_t *dependency);
+bool celix_dmServiceDependency_hasSetCallback(const celix_dm_service_dependency_t *dependency);
+bool celix_dmServiceDependency_hasAddCallback(const celix_dm_service_dependency_t *dependency);
+bool celix_dmServiceDependency_hasRemoveCallback(const celix_dm_service_dependency_t *dependency);
+
+bool celix_dmServiceDependency_isAvailable(celix_dm_service_dependency_t *dependency);
 bool celix_dmServiceDependency_isRequired(const celix_dm_service_dependency_t* dependency);
 bool celix_dmServiceDependency_isTrackerOpen(celix_dm_service_dependency_t* dependency);
 
diff --git a/libs/framework/src/framework.c b/libs/framework/src/framework.c
index 957003b..0cb8e21 100644
--- a/libs/framework/src/framework.c
+++ b/libs/framework/src/framework.c
@@ -69,14 +69,14 @@ static inline celix_framework_bundle_entry_t* fw_bundleEntry_create(celix_bundle
 
 static inline void fw_bundleEntry_waitTillUseCountIs(celix_framework_bundle_entry_t *entry, size_t desiredUseCount) {
     celixThreadMutex_lock(&entry->useMutex);
-    time_t start = time(NULL);
+    struct timespec start = celix_gettime(CLOCK_MONOTONIC);
     while (entry->useCount != desiredUseCount) {
         celixThreadCondition_timedwaitRelative(&entry->useCond, &entry->useMutex, 5, 0);
         if (entry->useCount != desiredUseCount) {
-            time_t now = time(NULL);
-            if ((now-start) > 5) {
+            struct timespec now = celix_gettime(CLOCK_MONOTONIC);
+            if (celix_difftime(&start, &now) > 5) {
                 fw_log(celix_frameworkLogger_globalLogger(), CELIX_LOG_LEVEL_WARNING, "Bundle '%s' (bnd id = %li) still in use. Use count is %u, desired is %li", celix_bundle_getSymbolicName(entry->bnd), entry->bndId, entry->useCount, desiredUseCount);
-                start = time(NULL);
+                start = celix_gettime(CLOCK_MONOTONIC);
             }
         }
     }
@@ -1990,7 +1990,7 @@ static void fw_handleEventRequest(celix_framework_t *framework, celix_framework_
         }
     }
 
-    if (event->doneCallback != NULL) {
+    if (event->doneCallback != NULL && !event->cancelled) {
         event->doneCallback(event->doneData);
     }
 }
diff --git a/libs/utils/src/array_list.c b/libs/utils/src/array_list.c
index 1013cc3..7de9365 100644
--- a/libs/utils/src/array_list.c
+++ b/libs/utils/src/array_list.c
@@ -372,9 +372,11 @@ celix_array_list_t* celix_arrayList_createWithEquals(celix_arrayList_equals_fp e
 }
 
 void celix_arrayList_destroy(celix_array_list_t *list) {
-    list->size = 0;
-    free(list->elementData);
-    free(list);
+    if (list != NULL) {
+        list->size = 0;
+        free(list->elementData);
+        free(list);
+    }
 }
 
 int celix_arrayList_size(const celix_array_list_t *list) {