Repository: celix Updated Branches: refs/heads/develop e3e6d1a4e -> 91ba2a168
CELIX-351: Adds a retained refs list per service listener, so that when service listener are removed correct cleanup can be done. Project: http://git-wip-us.apache.org/repos/asf/celix/repo Commit: http://git-wip-us.apache.org/repos/asf/celix/commit/e6bff9f5 Tree: http://git-wip-us.apache.org/repos/asf/celix/tree/e6bff9f5 Diff: http://git-wip-us.apache.org/repos/asf/celix/diff/e6bff9f5 Branch: refs/heads/develop Commit: e6bff9f584570fe21e6ac18e10f1c6b5a8c2e7af Parents: e3e6d1a Author: Pepijn Noltes <pepijnnol...@gmail.com> Authored: Thu Feb 11 13:09:46 2016 +0100 Committer: Pepijn Noltes <pepijnnol...@gmail.com> Committed: Thu Feb 11 13:09:46 2016 +0100 ---------------------------------------------------------------------- framework/private/src/framework.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/celix/blob/e6bff9f5/framework/private/src/framework.c ---------------------------------------------------------------------- diff --git a/framework/private/src/framework.c b/framework/private/src/framework.c index 691bb40..56b02cd 100644 --- a/framework/private/src/framework.c +++ b/framework/private/src/framework.c @@ -109,6 +109,7 @@ struct fw_serviceListener { bundle_pt bundle; service_listener_pt listener; filter_pt filter; + array_list_pt retainedReferences; }; typedef struct fw_serviceListener * fw_service_listener_pt; @@ -1379,6 +1380,7 @@ void fw_addServiceListener(framework_pt framework, bundle_pt bundle, service_lis bundle_context_pt context = NULL; fwListener->bundle = bundle; + arrayList_create(&fwListener->retainedReferences); if (sfilter != NULL) { filter_pt filter = filter_create(sfilter); fwListener->filter = filter; @@ -1447,8 +1449,22 @@ void fw_removeServiceListener(framework_pt framework, bundle_pt bundle, service_ arrayList_remove(framework->serviceListeners, i); i--; + + //unregistering retained service references. For these refs a unregister event will not be triggered. + int k; + int rSize = arrayList_size(element->retainedReferences); + for (k = 0; k < rSize; k += 1) { + service_reference_pt ref = arrayList_get(element->retainedReferences, i); + if (ref != NULL) { + serviceRegistry_ungetServiceReference(framework->registry, element->bundle, ref); // decrease retain counter + } else { + //TODO,FIXME ref is sometimes NULL. This should not happen, investigate why + } + } + element->bundle = NULL; filter_destroy(element->filter); + arrayList_destroy(element->retainedReferences); element->filter = NULL; element->listener = NULL; free(element); @@ -1605,12 +1621,11 @@ void fw_serviceChanged(framework_pt framework, service_event_type_e eventType, s serviceRegistry_getServiceReference(framework->registry, element->bundle, registration, &reference); - - //FIXME, TODO need to retain the service ref. If not bundles using the service_listener will crash. - //update service_listener users so that they retain references if the keep them. - //NOTE: that you are never sure that the UNREGISTERED event will by handle by an service_listener (could be gone)) + //NOTE: that you are never sure that the UNREGISTERED event will by handle by an service_listener. listener could be gone + //Every reference retained is therefore stored and called when a service listener is removed from the framework. if (eventType == OSGI_FRAMEWORK_SERVICE_EVENT_REGISTERED) { serviceRegistry_retainServiceReference(framework->registry, element->bundle, reference); + arrayList_add(element->retainedReferences, reference); //TODO improve by using set (or hashmap) instead of list } event->type = eventType; @@ -1621,7 +1636,8 @@ void fw_serviceChanged(framework_pt framework, service_event_type_e eventType, s serviceRegistry_ungetServiceReference(framework->registry, element->bundle, reference); if (eventType == OSGI_FRAMEWORK_SERVICE_EVENT_UNREGISTERING) { - serviceRegistry_ungetServiceReference(framework->registry, element->bundle, reference); // to counter retain + arrayList_removeElement(element->retainedReferences, reference); + serviceRegistry_ungetServiceReference(framework->registry, element->bundle, reference); // decrease retain counter } free(event);