Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 171584

Summary: Bundles are now in STARTING state for a long time
Product: [Eclipse Project] Equinox Reporter: Paul Webster <pwebster>
Component: FrameworkAssignee: equinox.framework-inbox <equinox.framework-inbox>
Status: RESOLVED WONTFIX QA Contact:
Severity: normal    
Priority: P3 CC: bokowski, eclipse, john.arthorne
Version: 3.3   
Target Milestone: ---   
Hardware: PC   
OS: All   
Whiteboard:
Attachments:
Description Flags
Demonstrating view action enabled
none
patch none

Description Paul Webster CLA 2007-01-24 13:56:43 EST
It seems with the work on http://wiki.eclipse.org/index.php/Lazy_Start_Bundles bundles are in the Bundle.STARTING state for a long time.

But we expect the bundles to be in STARTING while the start() method is running:

A bundle is in the <code>STARTING</code> state when the <code>start</code> method is active.

DJ might have mentioned the code is in ActionExpression.PluginStateExpression and BundleUtility#isActivated(*) ... it is used for declarative actions (action sets, view, editor, and context menu actions and tooblars) as part of displaying the user the correct state.

PW
Comment 1 Paul Webster CLA 2007-01-24 14:08:04 EST
Created attachment 57464 [details]
Demonstrating view action enabled

3 projects that can be imported.  Expected behaviour:

1. problem view has a button A1 disabled
2. click the Sample Action from the main menu
3. select a problem marker in the problem view
4. A1 becomes enabled.

PW
Comment 2 BJ Hargrave CLA 2007-01-24 15:12:41 EST
This change is part of the forthcoming OSGi 4.1 spec. It is in the current draft spec and Equinox is tracking the draft.

The STARTING state brackets the execution time of BundleActivator.start. That is, the while BundleActivator.start is executing, the bundle's state must be STARTING. However, the converse is not true. It is not the case that if the bundle's state is STARTING, then BundleActivator.start must be executing. 

This has never been the case. But with the Lazy Activation changes, the time period between state becoming STARTING and beginning execution of BundleActivator.start can now be arbitrarily long.

It is better to use the ACTIVE state to determine that a bundle is ACTIVE. A bundle cannot properly be considered activated while in the STARTING state as it's BundleActivator.start method has not completed execution and thus the bundles "activation" is indeterminate.
Comment 3 Thomas Watson CLA 2007-01-24 15:32:07 EST
Created attachment 57470 [details]
patch

BJ is right, but it is unclear whether the ui cares about bundles that are currently being activated (i.e. BundleActivator.start is being called) or not.  To me it seems like you would not care about bundles until they are completely activated in this case.  If that is the case then you can simple remove the Bundle.STARTING state check from the BundleUtility.isActivated method ...

return bundle != null && (bundle.getState() & (Bundle.ACTIVE | Bundle.STOPPING)) != 0;

Even checking for the STOPPING state here questionable here, I don't think it is very safe to consider something in the process of cleaning itself up as an activated bundle.

If you find that you really *do* care about bundles that are in the process of being activated then you will need to use a synchronous bundle listener to keep track of bundles in the STARTING state.  Here is a patch that does that.  I need a better understanding why you would need that before I can recommend this as a fix.
Comment 4 Paul Webster CLA 2007-01-24 15:45:32 EST
(In reply to comment #2)
> The STARTING state brackets the execution time of BundleActivator.start. That
> is, the while BundleActivator.start is executing, the bundle's state must be
> STARTING. However, the converse is not true. It is not the case that if the
> bundle's state is STARTING, then BundleActivator.start must be executing.

That is *exceptionally* unclear from the javadoc I quoted.  It says a bundle is in the STARTING state when the start() method is running ... it does not say "and for any arbitrary period before hand."  This javadoc is on the state, not on the start() method.

This looks like a breaking API change.

It seems to me that what you want is a LAZILY_AWAITING_ACTIVATION state for your lazy bundle activation policy between RESOLVED and STARTING.

PW
Comment 5 BJ Hargrave CLA 2007-01-24 16:13:07 EST
(In reply to comment #4)
> That is *exceptionally* unclear from the javadoc I quoted.  It says a bundle is
> in the STARTING state when the start() method is running ... it does not say
> "and for any arbitrary period before hand."  This javadoc is on the state, not
> on the start() method.

I agree the javadoc could be improved and I will do so.

> 
> This looks like a breaking API change.

I disagree that it is breaking API change. But code that made the assumption that STARTING == BundleActivator.start executing will be disappointed..

STARTING is meant to bracket a set of activities in starting a bundle (e.g. Bundle.start) of which BundleActivator.start execution is one (important) part.

> 
> It seems to me that what you want is a LAZILY_AWAITING_ACTIVATION state for
> your lazy bundle activation policy between RESOLVED and STARTING.
> 

Well, I think Tom experimented with adding another state like you suggest and it was a major disaster. State checking code (like isActivated) has problems with a new state. So we went with the current design.
Comment 6 BJ Hargrave CLA 2007-01-24 16:21:59 EST
(In reply to comment #5)
> (In reply to comment #4)
> > That is *exceptionally* unclear from the javadoc I quoted.  It says a bundle is
> > in the STARTING state when the start() method is running ... it does not say
> > "and for any arbitrary period before hand."  This javadoc is on the state, not
> > on the start() method.

Actually javadoc says:

"A bundle is in the STARTING state when the start method is active. A bundle must be in this state when the bundle's BundleActivator.start is called."

The start methods refered to in the first sentence is Bundle.start NOT BundleActivator.start. So it is true that the bundle is in the STARTING state while Bundle.start is active. This is essentially the behavior of lazy activation. The bundle is being started, but activation (calling BundleActivator.start) is delayed.

The second sentence in the quote is also correct.

The first sentence can be changes to say "when the Bundle.start method is active". Would that be more specific and clear? A sentence could also be added to state that a bundle may exist in the STARTING state for some time if it has a lazy activation policy.
Comment 7 Paul Webster CLA 2007-01-24 16:32:03 EST
(In reply to comment #6)
> 
> "A bundle is in the STARTING state when the start method is active. A bundle
> must be in this state when the bundle's BundleActivator.start is called."
> 
> The start methods refered to in the first sentence is Bundle.start

Yes, that was clear.  If you are saying that lazy activation flag calls Bundle#start() on these bundles on eclipse/equinox startup, leaving everything in the STARTING state, and at some time later the class loading forces the lazy activation I would have to agree with you.

PW
Comment 8 BJ Hargrave CLA 2007-01-24 17:00:52 EST
(In reply to comment #7)
> If you are saying that lazy activation flag calls
> Bundle#start() on these bundles on eclipse/equinox startup, leaving everything
> in the STARTING state, and at some time later the class loading forces the lazy
> activation I would have to agree with you.

Well Bundle.start is not actually called but effectively what you said happens.
Comment 9 Boris Bokowski CLA 2007-01-24 17:04:38 EST
API change or not, this seems to be an important behavioral change that should be in the porting guide.
Comment 10 Thomas Watson CLA 2007-01-24 17:05:26 EST
I did try adding some kind of LAZILY_AWAITING_ACTIVATION state as a valid
Bundle state.  But as BJ points out adding completely new states really seemed
to mess things up.  For example, we have many places through out the SDK that
check to see that a bundle is not in the INSTALLED or UNINSTALLED state.  For
what ever reason the developers decided to check for ...

(bundle.getState() & (RESOLVED | STARTING | ACTIVE | STOPPING)) != 0 

instead of just checking ...

(bundle.getState() & (INSTALLED | UNINSTALLED)) == 0 

so if we add a new state in between RESOLVED and STARTING then all of these
checks started to fail.
Comment 11 Paul Webster CLA 2007-01-24 18:43:55 EST
(In reply to comment #8)
> 
> Well Bundle.start is not actually called but effectively what you said happens.

But this brings me back to my original assertion ... if you're not calling Bundle#start(), then it's a breaking API change.  STARTING is the state while Bundle#start() is active.

Adding the new state might have explicitly broken some checks, but behaviour that used to be covered under the RESOLVED state has been moved to the STARTING state and this change has implicitly done the exact same thing, just less clearly.  And STARTING is now not about starting the Bundle, but also a LAZILY_AWAITING_ACTIVATION that it didn't use to cover.

I'm not saying that we don't have to fix our checks, but the explicit change is much more visible when we need to fix our checks than an implicit change (which  still means we need to fix our checks :-)

But shouldn't this go through some kind of "breaking API change" process?

PW
Comment 12 BJ Hargrave CLA 2007-01-24 19:21:44 EST
(In reply to comment #11)
> (In reply to comment #8)
> > 
> > Well Bundle.start is not actually called but effectively what you said happens.
> 
> But this brings me back to my original assertion ... if you're not calling
> Bundle#start(), then it's a breaking API change.  STARTING is the state while
> Bundle#start() is active.

The framework has never called Bundle.start when the framework is launched to start bundles. Bundle.start implies persistence of the start state. There is an internal method used to "resume" bundles. This is what I mean when I say Bundle.start is not actually called. The internal method is called.

You are attempting to state the converse it true. It is true that is during the (normal) execution of Bundle.start, the bundle state will be STARTING for some duration. The bundle state of STARTING does not imply the Bundle.start is executing (see previous paragraph).

> 
> Adding the new state might have explicitly broken some checks, but behaviour
> that used to be covered under the RESOLVED state has been moved to the STARTING

What behavior has been moved? I am curious since a lot of thought has gone into this design and I want to make sure we did not miss anything.


> state and this change has implicitly done the exact same thing, just less
> clearly.  And STARTING is now not about starting the Bundle, but also a
> LAZILY_AWAITING_ACTIVATION that it didn't use to cover.

The STARTING state always covered what we now call starting the the bundle and activating the bundle. With the new lazy activation design, we have introduced a pause between starting and activation (thus lazy activation and not lazy starting). One key requirement for this design is #10 in http://www2.osgi.org/Design/LazyStart :

"10. Lazy activation bundles MUST be able to participate in the service layer before the first class is loaded from the bundle. This requires that the BundleContext for a lazy activation bundle be available to component systems (e.g. Declarative Services, Spring-OSGi, etc.) before the bundle enters the ACTIVE state."

This is why lazy activation bundles are now in the STARTING state prior to activation instead of the RESOLVED state. A bundle cannot have a bundle context in the RESOLVED state and thus 3rd party bundles cannot register services on their behalf prior to activation.
> 
> I'm not saying that we don't have to fix our checks, but the explicit change is
> much more visible when we need to fix our checks than an implicit change (which
>  still means we need to fix our checks :-)
> 
> But shouldn't this go through some kind of "breaking API change" process?
> 
> PW
> 

Comment 13 Paul Webster CLA 2007-01-24 19:57:05 EST
From 40 minutes ago:

I realize I'm being pedantic here, so take this thread with a grain of salt :-)

I think its a breaking API change, and I would prefer the explicit state over the implicit case ... if it caught platform UI out, it could cause other downstream grief.

I can work with Tom to see what we in platform can or cannot do.

PW
Comment 14 Paul Webster CLA 2007-01-24 20:01:49 EST
(In reply to comment #12)
> 
> The framework has never called Bundle.start when the framework is launched to
> start bundles. Bundle.start implies persistence of the start state. There is an
> internal method used to "resume" bundles. This is what I mean when I say
> Bundle.start is not actually called. The internal method is called.

Ah, good point.  That swings me back to not breaking API :-)

> > 
> > Adding the new state might have explicitly broken some checks, but behaviour
> > that used to be covered under the RESOLVED state has been moved to the STARTING
> 
> What behavior has been moved? I am curious since a lot of thought has gone into
> this design and I want to make sure we did not miss anything.

A bundle awaiting lazy activation has always been in the RESOLVED state (as near as I can tell, for the last 2-3 years).  Now we're saying it's under the STARTING state ... that's a pretty major change.

Why not make it explicit and break state checks instead of implicit (and break state checks)?

PW
Comment 15 Paul Webster CLA 2007-01-26 13:15:00 EST
We'll fix platform ui under bug 171833
PW
Comment 16 Thomas Watson CLA 2007-03-30 15:49:43 EDT
The OSGi R4.1 specification is final.  We follow the R4.1 specification with respect to lazy activation policies.