Community
Participate
Working Groups
To reproduce: 1. Import plug-in from attached archive "ExamplePlugin.zip" to your developer workspace. 2. Debug Eclipse in a new workspace. 3. Create a new Java project. 4. Add an external class folder to some absolute path location. This can be done with right click on the project in Package Explorer -> Java build path -> libraries tab. 5. Close the debugged Eclipse. 6. Move the new workspace (created for step 2, move e.g. with mv on Linux). 7. Debug application "TestApplication.some_test_application" with breakpoints at: a) org.eclipse.jdt.internal.core.ExternalFoldersManager.openExternalFoldersProject(IProject, IProgressMonitor) (first line that calls "project.open()") b) Line 34 of TestApplication (calls "IVMInstall defaultJVM = JavaRuntime.getDefaultVMInstall();") c) Line 25 of Test Application (calls "System.out.println("job running");") 8. Observe breakpoints b) and c) being hit. 9. Resume the breakpoint b) (the one directly in the application code). 10. Observe the breakpoint a) being hit (the one in ExternalFoldersManager.openExternalFoldersProject()). 11. Resume the breakpoint c) (the one at the line of the WorkspaceJob defined in the application code). 12. Resume the breakpoint a). 13. Observe deadlock between main thread and the job defined in the application. See also https://bugs.eclipse.org/bugs/show_bug.cgi?id=252571#c0, this defines the reproduction steps from 1. to 6. The reproduction steps and example application are just for simplicity. Originally, we observed the following deadlock in one of the applications of our product: "Worker-1: Refreshing workspace" #32 prio=5 os_prio=0 tid=0x00007ffff13f3000 nid=0x1e085 in Object.wait() [0x00007fffb2435000] java.lang.Thread.State: RUNNABLE at org.eclipse.jdt.internal.core.JavaCorePreferenceModifyListener.<init>(JavaCorePreferenceModifyListener.java:26) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:423) at java.lang.Class.newInstance(Class.java:442) at org.eclipse.core.internal.registry.osgi.RegistryStrategyOSGI.createExecutableExtension(RegistryStrategyOSGI.java:190) at org.eclipse.core.internal.registry.ExtensionRegistry.createExecutableExtension(ExtensionRegistry.java:934) at org.eclipse.core.internal.registry.ConfigurationElement.createExecutableExtension(ConfigurationElement.java:246) at org.eclipse.core.internal.registry.ConfigurationElementHandle.createExecutableExtension(ConfigurationElementHandle.java:63) at org.eclipse.core.internal.preferences.PreferenceServiceRegistryHelper.addModifyListener(PreferenceServiceRegistryHelper.java:94) at org.eclipse.core.internal.preferences.PreferenceServiceRegistryHelper.getModifyListeners(PreferenceServiceRegistryHelper.java:208) at org.eclipse.core.internal.preferences.PreferencesService.firePreApplyEvent(PreferencesService.java:444) at org.eclipse.core.internal.preferences.PreferencesService.applyPreferences(PreferencesService.java:125) at org.eclipse.core.internal.resources.ProjectPreferences.read(ProjectPreferences.java:212) at org.eclipse.core.internal.resources.ProjectPreferences.updatePreferences(ProjectPreferences.java:280) at org.eclipse.core.internal.resources.File.updateMetadataFiles(File.java:390) at org.eclipse.core.internal.localstore.RefreshLocalVisitor.visit(RefreshLocalVisitor.java:306) at org.eclipse.core.internal.localstore.UnifiedTree.accept(UnifiedTree.java:118) at org.eclipse.core.internal.localstore.FileSystemResourceManager.refreshResource(FileSystemResourceManager.java:976) at org.eclipse.core.internal.localstore.FileSystemResourceManager.refresh(FileSystemResourceManager.java:959) at org.eclipse.core.internal.localstore.FileSystemResourceManager.refreshRoot(FileSystemResourceManager.java:1001) at org.eclipse.core.internal.localstore.FileSystemResourceManager.refresh(FileSystemResourceManager.java:952) at org.eclipse.core.internal.resources.Resource.refreshLocal(Resource.java:1550) at org.eclipse.core.internal.refresh.RefreshJob.runInWorkspace(RefreshJob.java:166) at org.eclipse.core.internal.resources.InternalWorkspaceJob.run(InternalWorkspaceJob.java:42) at org.eclipse.core.internal.jobs.Worker.run(Worker.java:63) "main" #1 prio=5 os_prio=0 tid=0x00007ffff004e000 nid=0x1e053 in Object.wait() [0x00007ffff59bb000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) at java.lang.Object.wait(Object.java:502) at org.eclipse.core.internal.jobs.ThreadJob.waitForRun(ThreadJob.java:316) - locked <0x00000004c334f150> (a java.lang.Object) at org.eclipse.core.internal.jobs.ThreadJob.joinRun(ThreadJob.java:205) at org.eclipse.core.internal.jobs.ImplicitJobs.begin(ImplicitJobs.java:95) at org.eclipse.core.internal.jobs.JobManager.beginRule(JobManager.java:297) at org.eclipse.core.internal.resources.WorkManager.checkIn(WorkManager.java:124) at org.eclipse.core.internal.resources.Workspace.prepareOperation(Workspace.java:2243) at org.eclipse.core.internal.resources.Project.open(Project.java:1021) at org.eclipse.core.internal.resources.Project.open(Project.java:1110) at org.eclipse.jdt.internal.core.ExternalFoldersManager.openExternalFoldersProject(ExternalFoldersManager.java:385) at org.eclipse.jdt.internal.core.ExternalFoldersManager.getFolders(ExternalFoldersManager.java:416) at org.eclipse.jdt.internal.core.ExternalFoldersManager.<init>(ExternalFoldersManager.java:74) at org.eclipse.jdt.internal.core.ExternalFoldersManager.getExternalFoldersManager(ExternalFoldersManager.java:80) - locked <0x00000007b6f88f98> (a java.lang.Class for org.eclipse.jdt.internal.core.ExternalFoldersManager) at org.eclipse.jdt.internal.core.JavaModelManager.<init>(JavaModelManager.java:625) at org.eclipse.jdt.internal.core.JavaModelManager.<clinit>(JavaModelManager.java:1236) at org.eclipse.jdt.core.JavaCore.start(JavaCore.java:6224) at org.eclipse.osgi.internal.framework.BundleContextImpl$3.run(BundleContextImpl.java:782) at org.eclipse.osgi.internal.framework.BundleContextImpl$3.run(BundleContextImpl.java:1) at java.security.AccessController.doPrivileged(Native Method) at org.eclipse.osgi.internal.framework.BundleContextImpl.startActivator(BundleContextImpl.java:775) at org.eclipse.osgi.internal.framework.BundleContextImpl.start(BundleContextImpl.java:732) at org.eclipse.osgi.internal.framework.EquinoxBundle.startWorker0(EquinoxBundle.java:1005) at org.eclipse.osgi.internal.framework.EquinoxBundle$EquinoxModule.startWorker(EquinoxBundle.java:357) at org.eclipse.osgi.container.Module.doStart(Module.java:584) at org.eclipse.osgi.container.Module.start(Module.java:452) at org.eclipse.osgi.framework.util.SecureAction.start(SecureAction.java:471) at org.eclipse.osgi.internal.hooks.EclipseLazyStarter.postFindLocalClass(EclipseLazyStarter.java:117) at org.eclipse.osgi.internal.loader.classpath.ClasspathManager.findLocalClass(ClasspathManager.java:557) at org.eclipse.osgi.internal.loader.ModuleClassLoader.findLocalClass(ModuleClassLoader.java:331) at org.eclipse.osgi.internal.loader.BundleLoader.findLocalClass(BundleLoader.java:395) at org.eclipse.osgi.internal.loader.sources.SingleSourcePackage.loadClass(SingleSourcePackage.java:39) at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:469) at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:422) at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:414) at org.eclipse.osgi.internal.loader.ModuleClassLoader.loadClass(ModuleClassLoader.java:153) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) at org.eclipse.jdt.internal.launching.LaunchingPlugin.start(LaunchingPlugin.java:581) at org.eclipse.osgi.internal.framework.BundleContextImpl$3.run(BundleContextImpl.java:782) at org.eclipse.osgi.internal.framework.BundleContextImpl$3.run(BundleContextImpl.java:1) at java.security.AccessController.doPrivileged(Native Method) at org.eclipse.osgi.internal.framework.BundleContextImpl.startActivator(BundleContextImpl.java:775) at org.eclipse.osgi.internal.framework.BundleContextImpl.start(BundleContextImpl.java:732) at org.eclipse.osgi.internal.framework.EquinoxBundle.startWorker0(EquinoxBundle.java:1005) at org.eclipse.osgi.internal.framework.EquinoxBundle$EquinoxModule.startWorker(EquinoxBundle.java:357) at org.eclipse.osgi.container.Module.doStart(Module.java:584) at org.eclipse.osgi.container.Module.start(Module.java:452) at org.eclipse.osgi.framework.util.SecureAction.start(SecureAction.java:471) at org.eclipse.osgi.internal.hooks.EclipseLazyStarter.postFindLocalClass(EclipseLazyStarter.java:117) at org.eclipse.osgi.internal.loader.classpath.ClasspathManager.findLocalClass(ClasspathManager.java:557) at org.eclipse.osgi.internal.loader.ModuleClassLoader.findLocalClass(ModuleClassLoader.java:331) at org.eclipse.osgi.internal.loader.BundleLoader.findLocalClass(BundleLoader.java:395) at org.eclipse.osgi.internal.loader.sources.SingleSourcePackage.loadClass(SingleSourcePackage.java:39) at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:469) at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:422) at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:414) at org.eclipse.osgi.internal.loader.ModuleClassLoader.loadClass(ModuleClassLoader.java:153) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ... Another similar deadlock we observed had the same stack for the main thread, and an auto-build job: "Worker-3: Building workspace" #37 prio=5 os_prio=0 tid=0x00007ffff048c800 nid=0x1016c in Object.wait() [0x00007fffafe73000] java.lang.Thread.State: RUNNABLE at org.eclipse.jdt.core.JavaCore.create(JavaCore.java:3470) at org.eclipse.jdt.internal.core.DynamicProjectReferences.getDependentProjects(DynamicProjectReferences.java:33) at org.eclipse.core.internal.resources.ProjectDescription.computeDynamicReferencesForProject(ProjectDescription.java:952) at org.eclipse.core.internal.resources.ProjectDescription.getAllBuildConfigReferences(ProjectDescription.java:268) at org.eclipse.core.internal.resources.Project.internalGetReferencedBuildConfigs(Project.java:795) at org.eclipse.core.internal.resources.Workspace.computeActiveBuildConfigGraph(Workspace.java:755) at org.eclipse.core.internal.resources.Workspace.getBuildGraph(Workspace.java:1620) at org.eclipse.core.internal.resources.Workspace.getBuildOrder(Workspace.java:1601) at org.eclipse.core.internal.events.AutoBuildJob.doBuild(AutoBuildJob.java:154) at org.eclipse.core.internal.events.AutoBuildJob.run(AutoBuildJob.java:244) at org.eclipse.core.internal.jobs.Worker.run(Worker.java:63) One of the first lines of code in our application is: JavaRuntime.getDefaultVMInstall() This results in opening the external folder links project, if external class folders exist in a Java project. To open the project, a project lock is required. However, the auto-build and refresh jobs hold the workspace root lock while accessing the Java model (due to preferences in the case of the refresh job). So we have a deadlock; OSGI somehow prevents the auto-build / refresh job from continuing due to the main thread.
Reproduction should be possible with the Eclipse IDE application. However I was not able to create a .settings/XYZ.pref file that causes preferences to be read, such that ProjectPreferences.read() is called. Note that the situation is *very* specific. Our workaround for now is to call RefreshManager.shutdown(), since our application which hangs is a standalone compiler. This reduces the probability of hanging in a "bad" workspace (see bug 252571 comment 0) by a lot.
Created attachment 276945 [details] Plug-in to reproduce the problem with. See reproduction steps in description.
The essence is basically: on startup, ExternalFoldersManager should not try to acquire workspace lock (because it will always happen in the context of JavaCore.start()): this will cause a deadlock with any thread holding the workspace lock and trying to access JDT core, because OSGI will prevent this code running until JDT bundle is activated.
New Gerrit change created: https://git.eclipse.org/r/134183
Gerrit change https://git.eclipse.org/r/134183 was merged to [master]. Commit: http://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/?id=591d513227a887d616febc09ad92919c330dc3fd
Thanks Simeon, for the patch!
Thanks for merging!
Verified for 4.11 M3 by code inspection.
This causes a warning in my workspace: "Access to enclosing method getFolders() from the type ExternalFoldersManager is emulated by a synthetic accessor method" (In ExternalFoldersManager.java, line 89) jdt.core is usually warning-free. Am I the only one who gets this?
Should we open a ticket for this?
(In reply to Simeon Andreev from comment #10) > Should we open a ticket for this? IMHO not needed, the change is trivial, I will just push a patch for 4.13.
New Gerrit change created: https://git.eclipse.org/r/142841
(In reply to Eclipse Genie from comment #12) > New Gerrit change created: https://git.eclipse.org/r/142841 To be merged in 4.13.
Gerrit change https://git.eclipse.org/r/142841 was merged to [master]. Commit: http://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/?id=d8cf470faa5d6433d6f05d7fe7f7ee0051608f69