[
https://issues.apache.org/jira/browse/FELIX-4913?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Pierre De Rop resolved FELIX-4913.
----------------------------------
Resolution: Fixed
> DM Optional callbacks may sometimes be invoked twice
> ----------------------------------------------------
>
> Key: FELIX-4913
> URL: https://issues.apache.org/jira/browse/FELIX-4913
> Project: Felix
> Issue Type: Bug
> Components: Dependency Manager
> Affects Versions: org.apache.felix.dependencymanager-r3
> Reporter: Pierre De Rop
> Assignee: Pierre De Rop
> Fix For: org.apache.felix.dependencymanager-r4
>
>
> The following use case is not currently supported by the DM state machine,
> which suffers from a bug where sometimes, when the use case happens, the same
> optional callback may be invoked twice.
> The following case is supported by DS, so DM should support it, regardless of
> the fact that the design of this use case is arguable/questionable:
> - there is a component B
> - there is a component BFactory (registered in the OSGI registry). And
> BFactory.createB() creates a B instance and simply registers it in the OSGi
> registry.
> - there is a A component that has two OPTIONAL dependencies:
> {code}
> A.bind(BFactory)
> A.bind(B b)
> {code}
> - Then A is created and is starting. Since BFactory is available, the DM
> state machine for A transits from the INSTANTIATED_AND_WAITING_FOR_REQUIRED
> into the TRACKING_OPTIONAL state:
> {code}
> if (oldState == ComponentState.INSTANTIATED_AND_WAITING_FOR_REQUIRED
> && newState == ComponentState.TRACKING_OPTIONAL) {
> invokeAutoConfigInstanceBoundDependencies();
> invokeAddRequiredInstanceBoundDependencies();
> invoke(m_callbackStart);
> invokeAddOptionalDependencies();
> registerService();
> notifyListeners(newState);
> return true;
> }
> {code}
> - then, when the invokeAddOptionalDependencies() is running, it is invoking
> A.bind(BFactory b). At this exact point, the A.bind(BFactory) method calls
> bf.createB():
> {code}
> A.bind(BFactory bf) {
> bf.createB();
> }
> {code}
> - this has the following side effect: a B service is synchronously registered
> in the OSGI service registry. So ComponentImpl.handleAdded() is called, and
> since we are in the
> TRACKING_OPTIONAL state (we are entering into this state), then the A.bindB(B
> b) callback is invoked.
> - BUT ... we are still running in the invokeAddOptionalDependencies() method.
> So when that method is about to iterate on the available services of the B
> dependency, then it calls a
> second time the "A.bind(B)" callback.
> I have a patch for this use case, which I have extensively tested since two
> days.
> To preserve my soul, the patch is simple and conservative: I use the same
> technique that was done in the ConfigurationDependencyImpl class: I'm using a
> cache of callbacks that ensures that the same callback won't be invoked more
> than one time. The advantage of this patch is that it does not make too much
> polutions in the state machine which is not altered too much.
> I will also commit a test case which demonstrates the issue.
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)