felix-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Thomas Watson (JIRA)" <j...@apache.org>
Subject [jira] [Created] (FELIX-5450) Fragments with multiple hosts can cause java.lang.ArrayIndexOutOfBoundsException
Date Thu, 15 Dec 2016 20:28:58 GMT
Thomas Watson created FELIX-5450:
------------------------------------

             Summary: Fragments with multiple hosts can cause java.lang.ArrayIndexOutOfBoundsException
                 Key: FELIX-5450
                 URL: https://issues.apache.org/jira/browse/FELIX-5450
             Project: Felix
          Issue Type: Bug
          Components: Resolver
    Affects Versions: resolver-1.10.0
            Reporter: Thomas Watson
            Assignee: Thomas Watson


The fix in FELIX-5389 for ShadowList is not complete.  There are still cases where the underlying
ArrayList from the CandidateSelector is reused in the ShadowList when it is not intended.
 This leads to exceptions like the following:

java.lang.ArrayIndexOutOfBoundsException: -1
	at java.util.ArrayList.elementData(ArrayList.java:418)
	at java.util.ArrayList.set(ArrayList.java:446)
	at org.apache.felix.resolver.util.ShadowList.replace(ShadowList.java:81)
	at org.apache.felix.resolver.Candidates.prepare(Candidates.java:915)
	at org.apache.felix.resolver.ResolverImpl.getInitialCandidates(ResolverImpl.java:502)
	at org.apache.felix.resolver.ResolverImpl.doResolve(ResolverImpl.java:387)
	at org.apache.felix.resolver.ResolverImpl.resolve(ResolverImpl.java:375)
	at org.apache.felix.resolver.ResolverImpl.resolve(ResolverImpl.java:368)

This is happening when there are multiple hosts for a single fragment and the fragment has
a requirement that is getting resolved to a candidate from another host resource that also
has at least one fragment.

The issue comes up when replacing the capability from the host with a wrapped capability for
the fragment requirement which is a payload requirement for more than one host.  It should
do this for each WrappedRequirement that is wrapping the payload requirement from the fragment
to each host.  The first WrappedRequirement has its candidates modified, but that changes
the shared ArrayList of the candidates for each of the other WrappedRequirements for the other
hosts.  The fix for this is to ensure the ArrayList from a CandidateSelector is never shared
with a ShadowList.

But once I fixed this I ran into another strange issue that ended up causing Uses constraint
errors like this:

org.osgi.service.resolver.ResolutionException: Uses constraint violation. Unable to resolve
resource host [osgi.identity; host] because it is exposed to package 'exporter' from resources
exporter [osgi.identity; exporter] and exporter [osgi.identity; exporter] via two dependency
chains.

Chain 1:
  host [osgi.identity; host]
    import: (osgi.wiring.package=exporter)
     |
    export: osgi.wiring.package: exporter
  exporter [osgi.identity; exporter]

Chain 2:
  host [osgi.identity; host]
    import: (osgi.wiring.package=exporter)
     |
    export: osgi.wiring.package: exporter
  exporter [osgi.identity; exporter]

This only happens if a fragment has more than one host and the fragment and host have a requirement
for a the same package.  Additionally the capability that satisfies the payload requirement
must come from a host that also has at least one fragment.  The issue here is how we are finding
CandidateSelectors of depending requirements when we need to replace a capability with a wrapped
capability.  There is a loop in the Candidates.prepare method which is says "Copy candidates
for fragment requirements to the host.".  This loop basically copies the candidates from the
original requirement from the fragment to a CandidateSelector for the WrappedRequirement for
the host.  But it also removes the original requirement from the dependents for the capability.
 If there are multiple hosts this becomes problematic because this dependency set is used
to find CandidateSelectors that need to be modified when wrapping a host.  But since we remove
the original requirement from the fragment that means any other hosts the fragment is attached
to will not be discovered and therefore will not have the original capability properly replaced
with the WrappedCapability.  That makes the consistency check fail and give this bogus message
that make it look like there are 2 identical chains leading to the identical capability. 
But the two capabilities are different because one is wrapped and one is not.

The fix is to separate out the inner loop that "Copy candidates for fragment requirements
to the host." to a outer loop that is done before the main loop over the hostResources.  This
way we properly setup all the CandidateSelector for the payload WrappedRequirements before
actually modifying the CandidateSelector capabilities with the WrappedCapabilities.

Super long story short:  Fragments are just horribly complex. 



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Mime
View raw message