This is an automated email from the ASF dual-hosted git repository.
pnoltes pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/celix.git
The following commit(s) were added to refs/heads/develop by this push:
new 52253e7 Fixes an issue where get a service from a service factory can
lead to a deadlock
52253e7 is described below
commit 52253e72605238388a385d42da181b63ea1b516d
Author: Pepijn Noltes <[email protected]>
AuthorDate: Fri May 24 17:32:19 2019 +0200
Fixes an issue where get a service from a service factory can lead to a
deadlock
---
.../src/simple_consumer_example.c | 2 +-
.../private/test/service_registry_test.cpp | 3 ++
libs/framework/src/service_registry.c | 34 +++++++++++++---------
3 files changed, 24 insertions(+), 15 deletions(-)
diff --git
a/examples/celix-examples/services_example_c/src/simple_consumer_example.c
b/examples/celix-examples/services_example_c/src/simple_consumer_example.c
index db1a4aa..e078f56 100644
--- a/examples/celix-examples/services_example_c/src/simple_consumer_example.c
+++ b/examples/celix-examples/services_example_c/src/simple_consumer_example.c
@@ -66,4 +66,4 @@ static celix_status_t activator_stop(activator_data_t *data,
celix_bundle_contex
return CELIX_SUCCESS;
}
-CELIX_GEN_BUNDLE_ACTIVATOR(activator_data_t, activator_start, activator_stop)
\ No newline at end of file
+CELIX_GEN_BUNDLE_ACTIVATOR(activator_data_t, activator_start, activator_stop)
diff --git a/libs/framework/private/test/service_registry_test.cpp
b/libs/framework/private/test/service_registry_test.cpp
index 6f8aabc..a0ee6eb 100644
--- a/libs/framework/private/test/service_registry_test.cpp
+++ b/libs/framework/private/test/service_registry_test.cpp
@@ -871,6 +871,9 @@ TEST(service_registry, getService) {
.expectOneCall("serviceRegistration_isValid")
.withParameter("registration", registration)
.andReturnValue(false);
+ mock()
+ .expectOneCall("serviceRegistration_retain")
+ .withParameter("registration", registration);
actual = (void*) 0x666;//generic non null pointer value
serviceRegistry_getService(registry, bundle, reference, &actual);
diff --git a/libs/framework/src/service_registry.c
b/libs/framework/src/service_registry.c
index ea7effd..3516342 100644
--- a/libs/framework/src/service_registry.c
+++ b/libs/framework/src/service_registry.c
@@ -656,34 +656,40 @@ celix_status_t
serviceRegistry_getService(service_registry_pt registry, bundle_p
service_registration_pt registration = NULL;
size_t count = 0;
const void *service = NULL;
+ bool valid = false;
reference_status_t refStatus;
-
celixThreadRwlock_readLock(®istry->lock);
serviceRegistry_checkReference(registry, reference, &refStatus);
if (refStatus == REF_ACTIVE) {
serviceReference_getServiceRegistration(reference, ®istration);
-
- if (serviceRegistration_isValid(registration)) {
+ valid = serviceRegistration_isValid(registration);
+ if (valid) {
+ serviceRegistration_retain(registration);
serviceReference_increaseUsage(reference, &count);
- if (count == 1) {
- serviceRegistration_getService(registration, bundle, &service);
- serviceReference_setService(reference, service);
- }
-
- /* NOTE the out argument of sr_getService should be 'const void**'
- To ensure backwards compatibility a cast is made instead.
- */
- serviceReference_getService(reference, (void **)out);
} else {
*out = NULL; //invalid service registration
}
+ }
+ celixThreadRwlock_unlock(®istry->lock);
+
+ if (valid && refStatus == REF_ACTIVE) {
+ if (count == 1) {
+ serviceRegistration_getService(registration, bundle, &service);
+ serviceReference_setService(reference, service);
+ }
+
+ /* NOTE the out argument of sr_getService should be 'const void**'
+ To ensure backwards compatibility a cast is made instead.
+ */
+ serviceReference_getService(reference, (void **)out);
} else {
- serviceRegistry_logIllegalReference(registry, reference, refStatus);
+ if (refStatus != REF_ACTIVE) {
+ serviceRegistry_logIllegalReference(registry, reference,
refStatus);
+ }
status = CELIX_BUNDLE_EXCEPTION;
}
- celixThreadRwlock_unlock(®istry->lock);
return status;
}