Bug 384619 - [xtext] Xtext plugins do not cancel and stop the jobs they starts
Summary: [xtext] Xtext plugins do not cancel and stop the jobs they starts
Status: NEW
Alias: None
Product: TMF
Classification: Modeling
Component: Xtext (show other bugs)
Version: 2.5.4   Edit
Hardware: Macintosh Mac OS X
: P3 minor (vote)
Target Milestone: ---   Edit
Assignee: Project Inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-07-09 10:56 EDT by Laurent CLA
Modified: 2015-11-11 04:14 EST (History)
1 user (show)

See Also:


Attachments
Makes the xtext.ui plugin's Activator cancel and wait for its plugins (1.04 KB, patch)
2012-07-10 04:14 EDT, Laurent CLA
no flags Details | Diff
Define families for xtext.ui's jobs (7.30 KB, patch)
2012-07-10 04:15 EDT, Laurent CLA
no flags Details | Diff
Define families for xtext.builder's jobs (2.24 KB, patch)
2012-07-10 04:15 EDT, Laurent CLA
no flags Details | Diff
Makes the xtext.builder plugin's Activator cancel and wait for its jobs (2.27 KB, patch)
2012-07-10 04:16 EDT, Laurent CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Laurent CLA 2012-07-09 10:56:59 EDT
Build Identifier: M20120208-0800

Plugins should cancel during shutdown the Jobs they scheduled.
If not, this may result in several errors depending on scheduling, one being:
Job found still running after platform shutdown. Jobs should be canceled by the plugin that scheduled them during shutdown: org.eclipse.xtext.ui.editor.validation.ValidationJob
or
Job found still running after platform shutdown. Jobs should be canceled by the plugin that scheduled them during shutdown: org.eclipse.xtext.ui.editor.occurrences.OccurrenceMarker$MarkOccurrenceJob

It also happened with BuildScheduler$BuildJob.

Another error may occur. As most other plugins have been stopped, the getDefault() or getInstance() methods implemented in subclasses of AbstractUiPlugin usually returns null. This may for example lead to the following error.

!ENTRY org.apache.log4j 4 0 2012-07-06 17:57:55.968
!MESSAGE org.eclipse.xtext.linking.lazy.LazyLinkingResource - resolution of uriFragment 'xtextLink_::0.2.19.6.0.0.0::0::/0' failed.

!STACK 0
com.google.inject.ProvisionException: Guice provision errors:

1) Error in custom provider, java.lang.IllegalStateException: The bundle has not been started!
at org.eclipse.xtext.service.MethodBasedModule.configure(MethodBasedModule.java:73)
while locating org.eclipse.xtext.resource.IResourceDescriptions

1 error
at com.google.inject.internal.InjectorImpl$4.get(InjectorImpl.java:987)
at org.eclipse.xtext.resource.impl.ResourceDescriptionsProvider.createResourceDescriptions(ResourceDescriptionsProvider.java:72)
...
at org.eclipse.core.internal.resources.Project.build(Project.java:124)
at org.eclipse.xtext.builder.impl.BuildScheduler$BuildJob.run(BuildScheduler.java:163)
at org.eclipse.core.internal.jobs.Worker.run(Worker.java:54)
Caused by: java.lang.IllegalStateException: The bundle has not been started!
at org.eclipse.xtext.ui.shared.Access$InternalProvider.get(Access.java:38)
at com.google.inject.internal.InternalFactoryToProviderAdapter.get(InternalFactoryToProviderAdapter.java:40)
...

This error happens because BuildScheduler$BuildJob is still running whereas org.eclipse.xtext.builder.internal.Activator.getDefault() (called at org.eclipse.xtext.ui.shared.Access$InternalProvider.get(Access.java:38)) returns null because the plugin org.eclipse.xtext.builder has already been stopped.


To fix this issue, it is either possible to register all jobs scheduled by a plugin in the plugin's Activator class, or all Jobs may override the Job#belongsTo(Object) to state that they belong to the family of their plugin and the Activator should try to cancel the jobs that belongs to its family.

Reproducible: Sometimes

Steps to Reproduce:
To reproduce the first error, put a break point in a job, do the necessary step to trigger this job and shutdown Eclipse.

To reproduce the second error launch Eclipse, put a breakpoint in BuildScheduler.scheduleBuildIfNecessary, close a project (a worker thread should be paused on your breakpoint), then try to shutdown Eclipse, then unpause your breakpoint.
Comment 1 Laurent CLA 2012-07-10 04:14:14 EDT
Created attachment 218485 [details]
Makes the xtext.ui plugin's Activator cancel and wait for its plugins
Comment 2 Laurent CLA 2012-07-10 04:15:01 EDT
Created attachment 218486 [details]
Define families for xtext.ui's jobs
Comment 3 Laurent CLA 2012-07-10 04:15:43 EDT
Created attachment 218487 [details]
Define families for xtext.builder's jobs
Comment 4 Laurent CLA 2012-07-10 04:16:45 EDT
Created attachment 218488 [details]
Makes the xtext.builder plugin's Activator cancel and wait for its jobs
Comment 5 Laurent CLA 2012-07-10 04:20:29 EDT
I made 4 patches.

builderFamilies.patch and xtextuiFamilies.patch define a family for each subclass of Job I have found in xtext.ui and xtext.builder plugins. As proposed in the bug report, I have used the plugin's Activator instance as a family. Therefore, jobs defined and scheduled in org.eclipse.xtext.builder belongs to org.eclipse.xtext.builder.internal.Activator.getDefault(), and jobs defined and scheduled in org.eclipse.xtext.ui belongs to org.eclipse.xtext.ui.internal.Activator.getDefault(). If a Job already had a family, it now belongs to 2 families at the same time.

builderActivator.patch cancels the jobs that belongs to the current plugin and then shows 3 possible implementations to wait for the jobs to terminate.
The first one is a simple call to IJobManager#join(Object,IProgressMonitor). It is efficient and "safe" (as it will never terminate if a job is still running, therefore it fully fixes the bug reported), but if a job is stuck then Eclipse will not terminate "in a timely fashion" (as required by the specification of BunderActivator#stop() ).
The second one is used in JobManager#doSutdown(). It is a bit less efficient (as it may wait up to 0.1 second even if all Jobs have terminated), it less safe as this method may exit even if some jobs have still not terminated (in less than .3 second), but this method always exit in a timely fashion.
The third one uses a second thread to wait for the other jobs, and wait this thread at most TIMEOUT (here 600 ms, but it can be changed). This implementation is efficient and it will always exit in a timely fashion, but, as for the second solution, it may also exit even if some jobs have not terminated yet.

Note that a job that has been requested to cancel its operation should terminate in a timely fashion, and if not it should have some good reason to do so (or it is a bug). Therefore it is probably a good idea to wait for it for a few seconds.
Comment 6 Laurent CLA 2014-09-02 06:10:26 EDT
MarkOccurrenceJob has changed since 2.3.0, so it cannot be reproduced with this Job, but it can still be reproduced with the ValidationJob, the UpdateEditorStateJob, DirtyStateEditorSupport$UpdateEditorStateJob, OutlineRefreshJob, and the XtextReconciler.

I have not been able to reproduce the second error with BuildScheduler.
Comment 7 Sven Efftinge CLA 2015-02-25 02:37:30 EST
Sorry, we didn't come around to look at this for 2.8. Postponing to 2.9.