You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@celix.apache.org by ab...@apache.org on 2014/08/27 14:14:30 UTC

svn commit: r1620872 - in /celix/trunk: framework/private/include/ framework/private/src/ framework/public/include/ shell/private/src/ shell_tui/private/src/

Author: abroekhuis
Date: Wed Aug 27 12:14:30 2014
New Revision: 1620872

URL: http://svn.apache.org/r1620872
Log:
Fixed a race condition in the registry. Introduced a new API call to unget ServiceReferences.

Modified:
    celix/trunk/framework/private/include/framework_private.h
    celix/trunk/framework/private/include/service_registration_private.h
    celix/trunk/framework/private/include/service_registry_private.h
    celix/trunk/framework/private/src/bundle_context.c
    celix/trunk/framework/private/src/framework.c
    celix/trunk/framework/private/src/service_reference.c
    celix/trunk/framework/private/src/service_registration.c
    celix/trunk/framework/private/src/service_registry.c
    celix/trunk/framework/public/include/bundle_context.h
    celix/trunk/framework/public/include/service_registry.h
    celix/trunk/shell/private/src/log_command.c
    celix/trunk/shell_tui/private/src/shell_tui.c

Modified: celix/trunk/framework/private/include/framework_private.h
URL: http://svn.apache.org/viewvc/celix/trunk/framework/private/include/framework_private.h?rev=1620872&r1=1620871&r2=1620872&view=diff
==============================================================================
--- celix/trunk/framework/private/include/framework_private.h (original)
+++ celix/trunk/framework/private/include/framework_private.h Wed Aug 27 12:14:30 2014
@@ -103,6 +103,7 @@ FRAMEWORK_EXPORT celix_status_t fw_regis
 FRAMEWORK_EXPORT void fw_unregisterService(service_registration_pt registration);
 
 FRAMEWORK_EXPORT celix_status_t fw_getServiceReferences(framework_pt framework, array_list_pt *references, bundle_pt bundle, const char * serviceName, char * filter);
+FRAMEWORK_EXPORT celix_status_t framework_ungetServiceReference(framework_pt framework, bundle_pt bundle, service_reference_pt reference);
 FRAMEWORK_EXPORT celix_status_t fw_getService(framework_pt framework, bundle_pt bundle, service_reference_pt reference, void **service);
 FRAMEWORK_EXPORT celix_status_t framework_ungetService(framework_pt framework, bundle_pt bundle, service_reference_pt reference, bool *result);
 FRAMEWORK_EXPORT celix_status_t fw_getBundleRegisteredServices(framework_pt framework, bundle_pt bundle, array_list_pt *services);

Modified: celix/trunk/framework/private/include/service_registration_private.h
URL: http://svn.apache.org/viewvc/celix/trunk/framework/private/include/service_registration_private.h?rev=1620872&r1=1620871&r2=1620872&view=diff
==============================================================================
--- celix/trunk/framework/private/include/service_registration_private.h (original)
+++ celix/trunk/framework/private/include/service_registration_private.h Wed Aug 27 12:14:30 2014
@@ -38,7 +38,6 @@ struct service {
 struct serviceRegistration {
 	service_registry_pt registry;
 	char * className;
-	array_list_pt references;
 	bundle_pt bundle;
 	properties_pt properties;
 	void * svcObj;

Modified: celix/trunk/framework/private/include/service_registry_private.h
URL: http://svn.apache.org/viewvc/celix/trunk/framework/private/include/service_registry_private.h?rev=1620872&r1=1620871&r2=1620872&view=diff
==============================================================================
--- celix/trunk/framework/private/include/service_registry_private.h (original)
+++ celix/trunk/framework/private/include/service_registry_private.h Wed Aug 27 12:14:30 2014
@@ -42,6 +42,8 @@ struct serviceRegistry {
 
 	celix_thread_mutex_t mutex;
 	celix_thread_mutexattr_t mutexAttr;
+
+	celix_thread_mutex_t referencesMapMutex;
 };
 
 struct usageCount {

Modified: celix/trunk/framework/private/src/bundle_context.c
URL: http://svn.apache.org/viewvc/celix/trunk/framework/private/src/bundle_context.c?rev=1620872&r1=1620871&r2=1620872&view=diff
==============================================================================
--- celix/trunk/framework/private/src/bundle_context.c (original)
+++ celix/trunk/framework/private/src/bundle_context.c Wed Aug 27 12:14:30 2014
@@ -208,6 +208,20 @@ celix_status_t bundleContext_getServiceR
 	return status;
 }
 
+celix_status_t bundleContext_ungetServiceReference(bundle_context_pt context, service_reference_pt reference) {
+    celix_status_t status = CELIX_SUCCESS;
+
+    if (context != NULL && reference != NULL) {
+        status = framework_ungetServiceReference(context->framework, context->bundle, reference);
+    } else {
+        status = CELIX_ILLEGAL_ARGUMENT;
+    }
+
+    framework_logIfError(logger, status, NULL, "Failed to unget service_reference");
+
+    return status;
+}
+
 celix_status_t bundleContext_getService(bundle_context_pt context, service_reference_pt reference, void **service_instance) {
     celix_status_t status = CELIX_SUCCESS;
 

Modified: celix/trunk/framework/private/src/framework.c
URL: http://svn.apache.org/viewvc/celix/trunk/framework/private/src/framework.c?rev=1620872&r1=1620871&r2=1620872&view=diff
==============================================================================
--- celix/trunk/framework/private/src/framework.c (original)
+++ celix/trunk/framework/private/src/framework.c Wed Aug 27 12:14:30 2014
@@ -859,32 +859,22 @@ celix_status_t fw_stopBundle(framework_p
                     status = CELIX_DO_IF(status, activator->destroy(activator->userData, context));
                 }
 	        }
-//	    }
-
-//	    status = CELIX_DO_IF(status, bundle_getCurrentModule(bundle, &module));
-//	    if (status == CELIX_SUCCESS) {
-//            if (strcmp(module_getId(module), "0") != 0) {
-//                if (activator != NULL) {
-//                    activator->start = NULL;
-//                    activator->stop = NULL;
-//                    activator->userData = NULL;
-//                    //free(activator);
-////                    status = CELIX_DO_IF(status, bundle_setActivator(bundle, NULL));
-//                }
 
             if (id != 0) {
                 status = CELIX_DO_IF(status, serviceRegistry_unregisterServices(framework->registry, bundle));
                 if (status == CELIX_SUCCESS) {
+                    module_pt module = NULL;
+                    char *symbolicName = NULL;
+                    long id = 0;
+                    bundle_getCurrentModule(bundle, &module);
+                    module_getSymbolicName(module, &symbolicName);
+                    bundle_getBundleId(bundle, &id);
+
                     serviceRegistry_ungetServices(framework->registry, bundle);
+                    serviceRegistry_ungetServiceReferences(framework->registry, bundle);
                 }
                 // #TODO remove listeners for bundle
 
-//                if (wasActive) {
-//                    if (activator->destroy != NULL) {
-//                        status = CELIX_DO_IF(status, activator->destroy(activator->userData, context));
-//                    }
-//                }
-
                 if (context != NULL) {
                     status = CELIX_DO_IF(status, bundleContext_destroy(context));
                     status = CELIX_DO_IF(status, bundle_setContext(bundle, NULL));
@@ -894,12 +884,6 @@ celix_status_t fw_stopBundle(framework_p
             }
 	    }
 
-//	    if (id == 0) {
-//            if (activator->destroy != NULL) {
-//                status = CELIX_DO_IF(status, activator->destroy(activator->userData, context));
-//            }
-//        }
-
 	    if (activator != NULL) {
 	        bundle_setActivator(bundle, NULL);
 	        free(activator);
@@ -1247,7 +1231,7 @@ celix_status_t fw_registerService(framew
 
                 bool ungetResult = false;
 
-                status = CELIX_DO_IF(status, serviceRegistry_createServiceReference(framework->registry, *registration, &ref));
+                status = CELIX_DO_IF(status, serviceRegistry_createServiceReference(framework->registry, framework->bundle, *registration, &ref));
                 status = CELIX_DO_IF(status, fw_getService(framework,framework->bundle, ref, (void **) &hook));
                 if (status == CELIX_SUCCESS) {
                     hook->added(hook->handle, infos);
@@ -1299,7 +1283,7 @@ celix_status_t fw_getServiceReferences(f
         filter = filter_create(sfilter);
 	}
 
-	status = CELIX_DO_IF(status, serviceRegistry_getServiceReferences(framework->registry, serviceName, filter, references));
+	status = CELIX_DO_IF(status, serviceRegistry_getServiceReferences(framework->registry, bundle, serviceName, filter, references));
 
 	if (filter != NULL) {
 		filter_destroy(filter);
@@ -1328,6 +1312,10 @@ celix_status_t fw_getServiceReferences(f
 	return status;
 }
 
+celix_status_t framework_ungetServiceReference(framework_pt framework, bundle_pt bundle, service_reference_pt reference) {
+    return serviceRegistry_ungetServiceReference(framework->registry, bundle, reference);
+}
+
 celix_status_t fw_getService(framework_pt framework, bundle_pt bundle, service_reference_pt reference, void **service) {
 	return serviceRegistry_getService(framework->registry, bundle, reference, service);
 }
@@ -1364,7 +1352,7 @@ void fw_addServiceListener(framework_pt 
 	fwListener->listener = listener;
 	arrayList_add(framework->serviceListeners, fwListener);
 
-	serviceRegistry_getListenerHooks(framework->registry, &listenerHooks);
+	serviceRegistry_getListenerHooks(framework->registry, framework->bundle, &listenerHooks);
 
 	info = (listener_hook_info_pt) malloc(sizeof(*info));
 
@@ -1434,7 +1422,7 @@ void fw_removeServiceListener(framework_
 	if (info != NULL) {
 		unsigned int i;
 		array_list_pt listenerHooks = NULL;
-		serviceRegistry_getListenerHooks(framework->registry, &listenerHooks);
+		serviceRegistry_getListenerHooks(framework->registry, framework->bundle, &listenerHooks);
 		
 		for (i = 0; i < arrayList_size(listenerHooks); i++) {
 			service_reference_pt ref = (service_reference_pt) arrayList_get(listenerHooks, i);
@@ -1559,7 +1547,7 @@ void fw_serviceChanged(framework_pt fram
 
 				event = (service_event_pt) malloc(sizeof(*event));
 
-				serviceRegistry_createServiceReference(framework->registry, registration, &reference);
+				serviceRegistry_createServiceReference(framework->registry, element->bundle, registration, &reference);
 
 				event->type = eventType;
 				event->reference = reference;
@@ -1581,7 +1569,7 @@ void fw_serviceChanged(framework_pt fram
 					service_reference_pt reference = NULL;
 					service_event_pt endmatch = (service_event_pt) malloc(sizeof(*endmatch));
 
-					serviceRegistry_createServiceReference(framework->registry, registration, &reference);
+					serviceRegistry_createServiceReference(framework->registry, element->bundle, registration, &reference);
 
 					endmatch->reference = reference;
 					endmatch->type = OSGI_FRAMEWORK_SERVICE_EVENT_MODIFIED_ENDMATCH;

Modified: celix/trunk/framework/private/src/service_reference.c
URL: http://svn.apache.org/viewvc/celix/trunk/framework/private/src/service_reference.c?rev=1620872&r1=1620871&r2=1620872&view=diff
==============================================================================
--- celix/trunk/framework/private/src/service_reference.c (original)
+++ celix/trunk/framework/private/src/service_reference.c Wed Aug 27 12:14:30 2014
@@ -55,7 +55,6 @@ celix_status_t serviceReference_create(b
 }
 
 celix_status_t serviceReference_destroy(service_reference_pt reference) {
-	serviceRegistry_removeReference(reference);
 	reference->bundle = NULL;
 	reference->registration = NULL;
 	free(reference);

Modified: celix/trunk/framework/private/src/service_registration.c
URL: http://svn.apache.org/viewvc/celix/trunk/framework/private/src/service_registration.c?rev=1620872&r1=1620871&r2=1620872&view=diff
==============================================================================
--- celix/trunk/framework/private/src/service_registration.c (original)
+++ celix/trunk/framework/private/src/service_registration.c Wed Aug 27 12:14:30 2014
@@ -63,8 +63,6 @@ celix_status_t serviceRegistration_creat
 		(*registration)->registry = registry;
 		(*registration)->className = strdup(serviceName);
 		(*registration)->bundle = bundle;
-		(*registration)->references = NULL;
-		arrayList_create(&(*registration)->references);
 
 		(*registration)->serviceId = serviceId;
 		(*registration)->svcObj = serviceObject;
@@ -74,8 +72,6 @@ celix_status_t serviceRegistration_creat
 			(*registration)->serviceFactory = NULL;
 		}
 
-		//	serviceReference_create(pool, bundle, *registration, &(*registration)->reference);
-
 		(*registration)->isUnregistering = false;
 		celixThreadMutex_create(&(*registration)->mutex, NULL);
 
@@ -93,7 +89,6 @@ celix_status_t serviceRegistration_destr
 	registration->registry = NULL;
 
 	properties_destroy(registration->properties);
-	arrayList_destroy(registration->references);
 
 	celixThreadMutex_destroy(&registration->mutex);
 
@@ -141,8 +136,6 @@ celix_status_t serviceRegistration_unreg
 	}
 	celixThreadMutex_unlock(&registration->mutex);
 
-//	bundle_pt bundle = NULL;
-//	status = serviceReference_getBundle(registration->reference, &bundle);
 	if (status == CELIX_SUCCESS) {
 		serviceRegistry_unregisterService(registration->registry, registration->bundle, registration);
 	}
@@ -204,7 +197,7 @@ celix_status_t serviceRegistration_getSe
 	celix_status_t status = CELIX_SUCCESS;
 
 	if (registration != NULL && *references == NULL) {
-		*references = registration->references;
+	    serviceRegistry_getServiceReferencesForRegistration(registration->registry, registration, references);
 	} else {
 		status = CELIX_ILLEGAL_ARGUMENT;
 	}

Modified: celix/trunk/framework/private/src/service_registry.c
URL: http://svn.apache.org/viewvc/celix/trunk/framework/private/src/service_registry.c?rev=1620872&r1=1620871&r2=1620872&view=diff
==============================================================================
--- celix/trunk/framework/private/src/service_registry.c (original)
+++ celix/trunk/framework/private/src/service_registry.c Wed Aug 27 12:14:30 2014
@@ -37,6 +37,10 @@
 #include "framework_private.h"
 #include "celix_log.h"
 
+static celix_status_t serviceRegistry_getUsageCount(service_registry_pt registry, bundle_pt bundle, service_reference_pt reference, usage_count_pt *usageCount);
+static celix_status_t serviceRegistry_addUsageCount(service_registry_pt registry, bundle_pt bundle, service_reference_pt reference, usage_count_pt *usageCount);
+static celix_status_t serviceRegistry_flushUsageCount(service_registry_pt registry, bundle_pt bundle, service_reference_pt reference);
+
 celix_status_t serviceRegistry_registerServiceInternal(service_registry_pt registry, bundle_pt bundle, char * serviceName, void * serviceObject, properties_pt dictionary, bool isFactory, service_registration_pt *registration);
 celix_status_t serviceRegistry_addHooks(service_registry_pt registry, char *serviceName, void *serviceObject, service_registration_pt registration);
 celix_status_t serviceRegistry_removeHook(service_registry_pt registry, service_registration_pt registration);
@@ -54,15 +58,13 @@ celix_status_t serviceRegistry_create(fr
 		(*registry)->serviceRegistrations = hashMap_create(NULL, NULL, NULL, NULL);
 		(*registry)->framework = framework;
 		(*registry)->currentServiceId = 1l;
-		(*registry)->serviceReferences = NULL;
+		(*registry)->serviceReferences = hashMap_create(NULL, NULL, NULL, NULL);;
 
 		arrayList_create(&(*registry)->listenerHooks);
 
-		celix_thread_mutexattr_t attr;
-
 		status = celixThreadMutexAttr_create(&(*registry)->mutexAttr);
 		status = CELIX_DO_IF(status, celixThreadMutexAttr_settype(&(*registry)->mutexAttr, CELIX_THREAD_MUTEX_RECURSIVE));
-		status = CELIX_DO_IF(status, celixThreadMutex_create(&(*registry)->mutex, &(*registry)->mutexAttr));
+		status = CELIX_DO_IF(status, celixThreadMutex_create(&(*registry)->referencesMapMutex, NULL));
 	}
 
 	framework_logIfError(logger, status, NULL, "Cannot create service registry");
@@ -73,9 +75,11 @@ celix_status_t serviceRegistry_create(fr
 celix_status_t serviceRegistry_destroy(service_registry_pt registry) {
     hashMap_destroy(registry->inUseMap, false, false);
     hashMap_destroy(registry->serviceRegistrations, false, false);
+    hashMap_destroy(registry->serviceReferences, false, false);
     arrayList_destroy(registry->listenerHooks);
     celixThreadMutex_destroy(&registry->mutex);
     celixThreadMutexAttr_destroy(&registry->mutexAttr);
+    celixThreadMutex_destroy(&registry->referencesMapMutex);
     registry->framework = NULL;
     registry->inUseMap = NULL;
     registry->listenerHooks = NULL;
@@ -86,19 +90,14 @@ celix_status_t serviceRegistry_destroy(s
     return CELIX_SUCCESS;
 }
 
-celix_status_t serviceRegistry_getUsageCount(service_registry_pt registry, bundle_pt bundle, service_reference_pt reference, usage_count_pt *usageCount) {
+static celix_status_t serviceRegistry_getUsageCount(service_registry_pt registry, bundle_pt bundle, service_reference_pt reference, usage_count_pt *usageCount) {
 	array_list_pt usages = (array_list_pt) hashMap_get(registry->inUseMap, bundle);
 	*usageCount = NULL;
 	unsigned int i;
 	for (i = 0; (usages != NULL) && (i < arrayList_size(usages)); i++) {
 		usage_count_pt usage = (usage_count_pt) arrayList_get(usages, i);
-		// @TODO use reference_equals!
 		bool equals = false;
-//		serviceReference_equals(usage->reference, reference, &equals);
-		if (usage->reference == reference) {
-			*usageCount = usage;
-			break;
-		}
+		serviceReference_equals(usage->reference, reference, &equals);
 		if (equals) {
 			*usageCount = usage;
 			break;
@@ -107,7 +106,7 @@ celix_status_t serviceRegistry_getUsageC
 	return CELIX_SUCCESS;
 }
 
-celix_status_t serviceRegistry_addUsageCount(service_registry_pt registry, bundle_pt bundle, service_reference_pt reference, usage_count_pt *usageCount) {
+static celix_status_t serviceRegistry_addUsageCount(service_registry_pt registry, bundle_pt bundle, service_reference_pt reference, usage_count_pt *usageCount) {
 	array_list_pt usages = hashMap_get(registry->inUseMap, bundle);
 	usage_count_pt usage = malloc(sizeof(*usage));
 	usage->reference = reference;
@@ -115,9 +114,7 @@ celix_status_t serviceRegistry_addUsageC
 	usage->service = NULL;
 
 	if (usages == NULL) {
-		module_pt mod = NULL;
 		arrayList_create(&usages);
-		bundle_getCurrentModule(bundle, &mod);
 	}
 	arrayList_add(usages, usage);
 	hashMap_put(registry->inUseMap, bundle, usages);
@@ -125,13 +122,15 @@ celix_status_t serviceRegistry_addUsageC
 	return CELIX_SUCCESS;
 }
 
-celix_status_t serviceRegistry_flushUsageCount(service_registry_pt registry, bundle_pt bundle, service_reference_pt reference) {
+static celix_status_t serviceRegistry_flushUsageCount(service_registry_pt registry, bundle_pt bundle, service_reference_pt reference) {
 	array_list_pt usages = hashMap_get(registry->inUseMap, bundle);
 	if (usages != NULL) {
 		array_list_iterator_pt iter = arrayListIterator_create(usages);
 		while (arrayListIterator_hasNext(iter)) {
 			usage_count_pt usage = arrayListIterator_next(iter);
-			if (usage->reference == reference) {
+			bool equals = false;
+			serviceReference_equals(usage->reference, reference, &equals);
+			if (equals) {
 				arrayListIterator_remove(iter);
 				free(usage);
 			}
@@ -150,6 +149,7 @@ celix_status_t serviceRegistry_flushUsag
 celix_status_t serviceRegistry_getRegisteredServices(service_registry_pt registry, bundle_pt bundle, array_list_pt *services) {
 	celix_status_t status = CELIX_SUCCESS;
 
+	celixThreadMutex_lock(&registry->mutex);
 	array_list_pt regs = (array_list_pt) hashMap_get(registry->serviceRegistrations, bundle);
 	if (regs != NULL) {
 		unsigned int i;
@@ -159,13 +159,14 @@ celix_status_t serviceRegistry_getRegist
 			service_registration_pt reg = arrayList_get(regs, i);
 			if (serviceRegistration_isValid(reg)) {
 				service_reference_pt reference = NULL;
-				status = serviceRegistry_createServiceReference(registry, reg, &reference);
+				status = serviceRegistry_createServiceReference(registry, bundle, reg, &reference);
 				if (status == CELIX_SUCCESS) {
 					arrayList_add(*services, reference);
 				}
 			}
 		}
 	}
+	celixThreadMutex_unlock(&registry->mutex);
 
 	framework_logIfError(logger, status, NULL, "Cannot get registered services");
 
@@ -255,11 +256,9 @@ celix_status_t serviceRegistry_unregiste
 		}
 		arrayList_destroy(clients);
 
-		// Disabled since a reference normally already is destroyed here.
-		// Compared to Java OSGi, this might result in crashes, since the references for the service are all destroyed
-		// Anyone still holding a pointer to such a reference is in risk, hence, always use a service tracker or similar!
-//		serviceReference_invalidate(reference);
+		serviceReference_invalidate(reference);
 	}
+	//TODO not needed, the registration is destroyed, any reference to the registration is invalid and will result in a segfault
 	serviceRegistration_invalidate(registration);
 
 	serviceRegistration_destroy(registration);
@@ -284,7 +283,9 @@ celix_status_t serviceRegistry_unregiste
 	}
 
 	if (regs != NULL && arrayList_isEmpty(regs)) {
+	    celixThreadMutex_lock(&registry->mutex);
 		array_list_pt removed = hashMap_remove(registry->serviceRegistrations, bundle);
+		celixThreadMutex_unlock(&registry->mutex);
 		arrayList_destroy(removed);
 		removed = NULL;
 	}
@@ -297,29 +298,66 @@ celix_status_t serviceRegistry_unregiste
 }
 
 
-celix_status_t serviceRegistry_createServiceReference(service_registry_pt registry, service_registration_pt registration, service_reference_pt *reference) {
+celix_status_t serviceRegistry_createServiceReference(service_registry_pt registry, bundle_pt owner, service_registration_pt registration, service_reference_pt *reference) {
 	celix_status_t status = CELIX_SUCCESS;
 
 	bundle_pt bundle = NULL;
-	array_list_pt references = NULL;
 
 	serviceRegistration_getBundle(registration, &bundle);
 	serviceReference_create(bundle, registration, reference);
 
-	serviceRegistration_getServiceReferences(registration, &references);
-	arrayList_add(references, *reference);
+	// Lock
+	celixThreadMutex_lock(&registry->referencesMapMutex);
+	array_list_pt references = hashMap_get(registry->serviceReferences, bundle);
+	if (references == NULL) {
+	    arrayList_create(&references);
+	}
+	arrayList_add(references, reference);
+	hashMap_put(registry->serviceReferences, bundle, references);
+
+	// Unlock
+	celixThreadMutex_unlock(&registry->referencesMapMutex);
 
 	framework_logIfError(logger, status, NULL, "Cannot create service reference");
 
 	return status;
 }
 
-celix_status_t serviceRegistry_getServiceReferences(service_registry_pt registry, const char *serviceName, filter_pt filter, array_list_pt *references) {
+celix_status_t serviceRegistry_getServiceReferencesForRegistration(service_registry_pt registry, service_registration_pt registration, array_list_pt *references) {
+    celix_status_t status = CELIX_SUCCESS;
+
+    hash_map_values_pt referenceValues = NULL;
+    hash_map_iterator_pt iterator = NULL;
+
+    arrayList_create(references);
+
+    celixThreadMutex_lock(&registry->referencesMapMutex);
+    referenceValues = hashMapValues_create(registry->serviceReferences);
+    iterator = hashMapValues_iterator(referenceValues);
+    while (hashMapIterator_hasNext(iterator)) {
+        array_list_pt refs = (array_list_pt) hashMapIterator_nextValue(iterator);
+        unsigned int refIdx;
+        for (refIdx = 0; (refs != NULL) && refIdx < arrayList_size(refs); refIdx++) {
+            service_registration_pt reg = NULL;
+            service_reference_pt reference = (service_reference_pt) arrayList_get(refs, refIdx);
+            serviceReference_getServiceRegistration(reference, &reg);
+            if (reg == registration) {
+                arrayList_add(*references, reference);
+            }
+        }
+    }
+    celixThreadMutex_unlock(&registry->referencesMapMutex);
+
+    return status;
+}
+
+celix_status_t serviceRegistry_getServiceReferences(service_registry_pt registry, bundle_pt owner, const char *serviceName, filter_pt filter, array_list_pt *references) {
 	celix_status_t status = CELIX_SUCCESS;
 	hash_map_values_pt registrations;
 	hash_map_iterator_pt iterator;
 	arrayList_create(references);
 
+	celixThreadMutex_lock(&registry->mutex);
 	registrations = hashMapValues_create(registry->serviceRegistrations);
 	iterator = hashMapValues_iterator(registrations);
 	while (hashMapIterator_hasNext(iterator)) {
@@ -352,7 +390,7 @@ celix_status_t serviceRegistry_getServic
 				if (matched) {
 					if (serviceRegistration_isValid(registration)) {
 						service_reference_pt reference = NULL;
-						serviceRegistry_createServiceReference(registry, registration, &reference);
+						serviceRegistry_createServiceReference(registry, owner, registration, &reference);
 						arrayList_add(*references, reference);
 					}
 				}
@@ -361,26 +399,62 @@ celix_status_t serviceRegistry_getServic
 	}
 	hashMapIterator_destroy(iterator);
 	hashMapValues_destroy(registrations);
+	celixThreadMutex_unlock(&registry->mutex);
 
 	framework_logIfError(logger, status, NULL, "Cannot get service references");
 
 	return status;
 }
 
-celix_status_t serviceRegistry_removeReference(service_reference_pt reference) {
-	service_registration_pt registration = NULL;
-	serviceReference_getServiceRegistration(reference, &registration);
+celix_status_t serviceRegistry_ungetServiceReference(service_registry_pt registry, bundle_pt owner, service_reference_pt reference) {
+    celix_status_t status = CELIX_SUCCESS;
 
-	if (registration != NULL) {
-		array_list_pt references = NULL;
-		serviceRegistration_getServiceReferences(registration, &references);
-		arrayList_removeElement(references, reference);
-	}
+    bool valid = false;
+    serviceRefernce_isValid(reference, &valid);
+    if (valid) {
+        bool ungetResult = true;
+        while (ungetResult) {
+            serviceRegistry_ungetService(registry, owner, reference, &ungetResult);
+        }
+    }
+
+    celixThreadMutex_lock(&registry->referencesMapMutex);
+    array_list_pt references = hashMap_get(registry->serviceReferences, owner);
+    if (references != NULL) {
+        arrayList_removeElement(references, reference);
+        if (arrayList_size(references) > 0) {
+            hashMap_put(registry->serviceReferences, owner, references);
+        } else {
+            array_list_pt removed = hashMap_remove(registry->serviceReferences, owner);
+            arrayList_destroy(removed);
+        }
+    }
+    celixThreadMutex_unlock(&registry->referencesMapMutex);
 
-	return CELIX_SUCCESS;
+	return status;
+}
+
+celix_status_t serviceRegistry_ungetServiceReferences(service_registry_pt registry, bundle_pt owner) {
+    celix_status_t status = CELIX_SUCCESS;
+
+    celixThreadMutex_lock(&registry->referencesMapMutex);
+    array_list_pt references = hashMap_get(registry->serviceReferences, owner);
+    celixThreadMutex_unlock(&registry->referencesMapMutex);
+
+    if (references != NULL) {
+        array_list_pt referencesClone = arrayList_clone(references);
+        int refIdx = 0;
+        for (refIdx = 0; refIdx < arrayList_size(referencesClone); refIdx++) {
+            service_reference_pt reference = arrayList_get(referencesClone, refIdx);
+            serviceRegistry_ungetServiceReference(registry, owner, reference);
+        }
+    }
+
+    return status;
 }
 
 celix_status_t serviceRegistry_getServicesInUse(service_registry_pt registry, bundle_pt bundle, array_list_pt *services) {
+    celixThreadMutex_lock(&registry->mutex);
 	array_list_pt usages = hashMap_get(registry->inUseMap, bundle);
 	if (usages != NULL) {
 		unsigned int i;
@@ -391,6 +465,7 @@ celix_status_t serviceRegistry_getServic
 			arrayList_add(*services, usage->reference);
 		}
 	}
+	celixThreadMutex_unlock(&registry->mutex);
 	return CELIX_SUCCESS;
 }
 
@@ -444,10 +519,9 @@ celix_status_t serviceRegistry_ungetServ
 
 	usage->count--;
 
-	if ((serviceRegistration_isValid(registration)) || (usage->count <= 0)) {
+	if ((!serviceRegistration_isValid(registration)) || (usage->count <= 0)) {
 		usage->service = NULL;
 		serviceRegistry_flushUsageCount(registry, bundle, reference);
-		serviceReference_destroy(reference);
 	}
 
 	celixThreadMutex_unlock(&registry->mutex);
@@ -489,6 +563,8 @@ array_list_pt serviceRegistry_getUsingBu
 	array_list_pt bundles = NULL;
 	hash_map_iterator_pt iter;
 	arrayList_create(&bundles);
+
+	celixThreadMutex_lock(&registry->mutex);
 	iter = hashMapIterator_create(registry->inUseMap);
 	while (hashMapIterator_hasNext(iter)) {
 		hash_map_entry_pt entry = hashMapIterator_nextEntry(iter);
@@ -497,12 +573,15 @@ array_list_pt serviceRegistry_getUsingBu
 		unsigned int i;
 		for (i = 0; i < arrayList_size(usages); i++) {
 			usage_count_pt usage = arrayList_get(usages, i);
-			if (usage->reference == reference) {
+			bool equals = false;
+			serviceReference_equals(usage->reference, reference, &equals);
+			if (equals) {
 				arrayList_add(bundles, bundle);
 			}
 		}
 	}
 	hashMapIterator_destroy(iter);
+	celixThreadMutex_unlock(&registry->mutex);
 	return bundles;
 }
 
@@ -510,7 +589,9 @@ celix_status_t serviceRegistry_addHooks(
 	celix_status_t status = CELIX_SUCCESS;
 
 	if (strcmp(OSGI_FRAMEWORK_LISTENER_HOOK_SERVICE_NAME, serviceName) == 0) {
+	    celixThreadMutex_lock(&registry->mutex);
 		arrayList_add(registry->listenerHooks, registration);
+		celixThreadMutex_unlock(&registry->mutex);
 	}
 
 	return status;
@@ -524,13 +605,15 @@ celix_status_t serviceRegistry_removeHoo
 	serviceRegistration_getProperties(registration, &props);
 	serviceName = properties_get(props, (char *) OSGI_FRAMEWORK_OBJECTCLASS);
 	if (strcmp(OSGI_FRAMEWORK_LISTENER_HOOK_SERVICE_NAME, serviceName) == 0) {
+	    celixThreadMutex_lock(&registry->mutex);
 		arrayList_removeElement(registry->listenerHooks, registration);
+		celixThreadMutex_unlock(&registry->mutex);
 	}
 
 	return status;
 }
 
-celix_status_t serviceRegistry_getListenerHooks(service_registry_pt registry, array_list_pt *hooks) {
+celix_status_t serviceRegistry_getListenerHooks(service_registry_pt registry, bundle_pt owner, array_list_pt *hooks) {
 	celix_status_t status = CELIX_SUCCESS;
 
 	if (registry == NULL || *hooks != NULL) {
@@ -539,12 +622,14 @@ celix_status_t serviceRegistry_getListen
 		status = arrayList_create(hooks);
 		if (status == CELIX_SUCCESS) {
 			unsigned int i;
+			celixThreadMutex_lock(&registry->mutex);
 			for (i = 0; i < arrayList_size(registry->listenerHooks); i++) {
 				service_registration_pt registration = arrayList_get(registry->listenerHooks, i);
 				service_reference_pt reference = NULL;
-				serviceRegistry_createServiceReference(registry, registration, &reference);
+				serviceRegistry_createServiceReference(registry, owner, registration, &reference);
 				arrayList_add(*hooks, reference);
 			}
+			celixThreadMutex_unlock(&registry->mutex);
 		}
 	}
 

Modified: celix/trunk/framework/public/include/bundle_context.h
URL: http://svn.apache.org/viewvc/celix/trunk/framework/public/include/bundle_context.h?rev=1620872&r1=1620871&r2=1620872&view=diff
==============================================================================
--- celix/trunk/framework/public/include/bundle_context.h (original)
+++ celix/trunk/framework/public/include/bundle_context.h Wed Aug 27 12:14:30 2014
@@ -58,6 +58,7 @@ FRAMEWORK_EXPORT celix_status_t bundleCo
 
 FRAMEWORK_EXPORT celix_status_t bundleContext_getServiceReferences(bundle_context_pt context, const char * serviceName, char * filter, array_list_pt *service_references);
 FRAMEWORK_EXPORT celix_status_t bundleContext_getServiceReference(bundle_context_pt context, char * serviceName, service_reference_pt *service_reference);
+FRAMEWORK_EXPORT celix_status_t bundleContext_ungetServiceReference(bundle_context_pt context, service_reference_pt reference);
 
 FRAMEWORK_EXPORT celix_status_t bundleContext_getService(bundle_context_pt context, service_reference_pt reference, void **service_instance);
 FRAMEWORK_EXPORT celix_status_t bundleContext_ungetService(bundle_context_pt context, service_reference_pt reference, bool *result);

Modified: celix/trunk/framework/public/include/service_registry.h
URL: http://svn.apache.org/viewvc/celix/trunk/framework/public/include/service_registry.h?rev=1620872&r1=1620871&r2=1620872&view=diff
==============================================================================
--- celix/trunk/framework/public/include/service_registry.h (original)
+++ celix/trunk/framework/public/include/service_registry.h Wed Aug 27 12:14:30 2014
@@ -47,17 +47,19 @@ celix_status_t serviceRegistry_registerS
 celix_status_t serviceRegistry_registerServiceFactory(service_registry_pt registry, bundle_pt bundle, char * serviceName, service_factory_pt factory, properties_pt dictionary, service_registration_pt *registration);
 celix_status_t serviceRegistry_unregisterService(service_registry_pt registry, bundle_pt bundle, service_registration_pt registration);
 celix_status_t serviceRegistry_unregisterServices(service_registry_pt registry, bundle_pt bundle);
-celix_status_t serviceRegistry_getServiceReferences(service_registry_pt registry, const char *serviceName, filter_pt filter, array_list_pt *references);
+celix_status_t serviceRegistry_getServiceReferences(service_registry_pt registry, bundle_pt bundle, const char *serviceName, filter_pt filter, array_list_pt *references);
 celix_status_t serviceRegistry_getService(service_registry_pt registry, bundle_pt bundle, service_reference_pt reference, void **service);
 celix_status_t serviceRegistry_ungetService(service_registry_pt registry, bundle_pt bundle, service_reference_pt reference, bool *result);
 void serviceRegistry_ungetServices(service_registry_pt registry, bundle_pt bundle);
 array_list_pt serviceRegistry_getUsingBundles(service_registry_pt registry, service_reference_pt reference);
 service_registration_pt serviceRegistry_findRegistration(service_registry_pt registry, service_reference_pt reference);
+celix_status_t serviceRegistry_ungetServiceReference(service_registry_pt registry, bundle_pt bundle, service_reference_pt reference);
+celix_status_t serviceRegistry_ungetServiceReferences(service_registry_pt registry, bundle_pt bundle);
 
-celix_status_t serviceRegistry_createServiceReference(service_registry_pt registry, service_registration_pt registration, service_reference_pt *reference);
-celix_status_t serviceRegistry_removeReference(service_reference_pt reference);
+celix_status_t serviceRegistry_createServiceReference(service_registry_pt registry, bundle_pt bundle, service_registration_pt registration, service_reference_pt *reference);
+celix_status_t serviceRegistry_getServiceReferencesForRegistration(service_registry_pt registry, service_registration_pt registration, array_list_pt *references);
 
-celix_status_t serviceRegistry_getListenerHooks(service_registry_pt registry, array_list_pt *hooks);
+celix_status_t serviceRegistry_getListenerHooks(service_registry_pt registry, bundle_pt bundle, array_list_pt *hooks);
 
 celix_status_t serviceRegistry_servicePropertiesModified(service_registry_pt registry, service_registration_pt registration, properties_pt oldprops);
 

Modified: celix/trunk/shell/private/src/log_command.c
URL: http://svn.apache.org/viewvc/celix/trunk/shell/private/src/log_command.c?rev=1620872&r1=1620871&r2=1620872&view=diff
==============================================================================
--- celix/trunk/shell/private/src/log_command.c (original)
+++ celix/trunk/shell/private/src/log_command.c Wed Aug 27 12:14:30 2014
@@ -93,10 +93,13 @@ void logCommand_execute(command_pt comma
                 }
             }
             linkedListIterator_destroy(iter);
+            bool result = true;
+            bundleContext_ungetService(command->bundleContext, readerService, &result);
             apr_pool_destroy(memory_pool);
         } else {
             out("Log reader service: out of memory!\n");
         }
+        bundleContext_ungetServiceReference(command->bundleContext, readerService);
     } else {
         out("No log reader available\n");
     }

Modified: celix/trunk/shell_tui/private/src/shell_tui.c
URL: http://svn.apache.org/viewvc/celix/trunk/shell_tui/private/src/shell_tui.c?rev=1620872&r1=1620871&r2=1620872&view=diff
==============================================================================
--- celix/trunk/shell_tui/private/src/shell_tui.c (original)
+++ celix/trunk/shell_tui/private/src/shell_tui.c Wed Aug 27 12:14:30 2014
@@ -96,10 +96,13 @@ void shellTui_initializeService(shell_tu
 void shellTui_serviceChanged(service_listener_pt listener, service_event_pt event) {
 	bool result = false;
     shell_tui_activator_pt act = (shell_tui_activator_pt) listener->handle;
+    bool equals = false;
+
+    serviceReference_equals(act->reference, event->reference, &equals);
 
 	if ((event->type == OSGI_FRAMEWORK_SERVICE_EVENT_REGISTERED) && (act->reference == NULL)) {
 		shellTui_initializeService(act);
-	} else if ((event->type == OSGI_FRAMEWORK_SERVICE_EVENT_UNREGISTERING) && (act->reference == event->reference)) {
+	} else if ((event->type == OSGI_FRAMEWORK_SERVICE_EVENT_UNREGISTERING) && (equals)) {
 		bundleContext_ungetService(act->context, act->reference, &result);
 		act->reference = NULL;
 		act->shell = NULL;