Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ClasspathUpdaterTest randomly fails #820

Closed
laeubi opened this issue Oct 26, 2023 · 19 comments · Fixed by #1601
Closed

ClasspathUpdaterTest randomly fails #820

laeubi opened this issue Oct 26, 2023 · 19 comments · Fixed by #1601
Labels
test Test case failure

Comments

@laeubi
Copy link
Contributor

laeubi commented Oct 26, 2023

See https://github.com/eclipse-pde/eclipse.pde/runs/18054276230

Update Classpath Job failed: Status ERROR: org.eclipse.pde.ui code=0 Updating failed. See log for details. Java Model Exception: Error in Java Model (code 1006): library.jar [in classpathupdater] is not on its project's build path
java.lang.AssertionError: Update Classpath Job failed: Status ERROR: org.eclipse.pde.ui code=0 Updating failed. See log for details. Java Model Exception: Error in Java Model (code 1006): library.jar [in classpathupdater] is not on its project's build path
	at org.junit.Assert.fail(Assert.java:89)
	at org.junit.Assert.assertTrue(Assert.java:42)
	at org.eclipse.pde.ui.tests.classpathupdater.ClasspathUpdaterTest.runUpdateClasspathJob(ClasspathUpdaterTest.java:185)
	at org.eclipse.pde.ui.tests.classpathupdater.ClasspathUpdaterTest.test_CreateFromScratch(ClasspathUpdaterTest.java:119)
	at org.eclipse.pde.ui.tests.classpathupdater.ClasspathUpdaterTest.test_CreateFromScatch_WithTestPluginName(ClasspathUpdaterTest.java:141)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
	at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
	at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
	at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
	at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
	at org.eclipse.pde.ui.tests.runtime.TestUtils$1.evaluate(TestUtils.java:276)

@iloveeclipse do you have any clue what might be the culprit here? We also see instabilities on Java 21 as reported here:

so this test seem to do something "special" or has a timing problem...

@laeubi laeubi changed the title ClasspathUpdaterTest radomly fails ClasspathUpdaterTest randomly fails Oct 26, 2023
@jukzi
Copy link
Contributor

jukzi commented Feb 3, 2025

also
https://download.eclipse.org/eclipse/downloads/drops4/I20250202-1800/testresults/html/org.eclipse.pde.ui.tests_ep435I-unit-macosx-x86_64-java21_macosx.cocoa.x86_64_21.html

failed both test_CreateFromScratch and test_CreateFromScatch_WithTestPluginName with same error about missing library.jar

@jukzi jukzi added the test Test case failure label Feb 3, 2025
@laeubi
Copy link
Contributor Author

laeubi commented Feb 3, 2025

I assume it is a JDT job running in the background, what I did somewhere else is before starting an action, install a job listener that puts all scheduled jobs in a list, then after the action I join on all these jobs (with a timeout) that way it is ensured that all jobs that are scheduled during an operation (e.g. update the classpath in the background) complete.

Another option would be to retry the assertions for some time until they eventually succeed.

@jukzi
Copy link
Contributor

jukzi commented Feb 5, 2025

@jukzi
Copy link
Contributor

jukzi commented Feb 5, 2025

cc @haubi because test was submitted with #497

@jukzi
Copy link
Contributor

jukzi commented Feb 5, 2025

can be locally reproduced on win:

Image

@jukzi
Copy link
Contributor

jukzi commented Feb 5, 2025

logged stacktrace of root cause:

Java Model Exception: Error in Java Model (code 1006): library.jar [in classpathupdater] is not on its project's build path
	at org.eclipse.jdt.internal.core.PackageFragmentRoot.getRawClasspathEntry(PackageFragmentRoot.java:622)
	at org.eclipse.pde.internal.core.ClasspathComputer.addLibraryEntry(ClasspathComputer.java:270)
	at org.eclipse.pde.internal.core.ClasspathComputer.addSourceAndLibraries(ClasspathComputer.java:149)
	at org.eclipse.pde.internal.core.ClasspathComputer.getClasspath(ClasspathComputer.java:89)
	at org.eclipse.pde.internal.core.ClasspathComputer.setClasspath(ClasspathComputer.java:69)
	at org.eclipse.pde.internal.ui.wizards.tools.UpdateClasspathJob.updateClasspath(UpdateClasspathJob.java:72)
	at org.eclipse.pde.internal.ui.wizards.tools.UpdateClasspathJob$1.runInWorkspace(UpdateClasspathJob.java:47)
	at org.eclipse.core.internal.resources.InternalWorkspaceJob.run(InternalWorkspaceJob.java:43)
	at org.eclipse.core.internal.jobs.Worker.run(Worker.java:63)

@jukzi
Copy link
Contributor

jukzi commented Feb 5, 2025

org.eclipse.jdt.internal.core.JavaModelManager.PerProjectInfo.rootPathToRawEntries is set in

 Thread [Worker-1: Updating workspace] (Suspended (breakpoint at line 1406 in org.eclipse.jdt.internal.core.JavaModelManager$PerProjectInfo))	
	owns: org.eclipse.jdt.internal.core.JavaModelManager$PerProjectInfo  (id=167)	
	org.eclipse.jdt.internal.core.JavaModelManager$PerProjectInfo.setClasspath(org.eclipse.jdt.core.IClasspathEntry[], org.eclipse.jdt.core.IClasspathEntry[], org.eclipse.core.runtime.IPath, org.eclipse.jdt.core.IJavaModelStatus, org.eclipse.jdt.core.IClasspathEntry[], java.util.Map<org.eclipse.core.runtime.IPath,org.eclipse.jdt.core.IClasspathEntry>, java.util.Map<org.eclipse.core.runtime.IPath,org.eclipse.jdt.core.IClasspathEntry>, org.eclipse.jdt.core.IJavaModelStatus, boolean) line: 1406	
	org.eclipse.jdt.internal.core.JavaModelManager$PerProjectInfo.setResolvedClasspath(org.eclipse.jdt.core.IClasspathEntry[], org.eclipse.jdt.core.IClasspathEntry[], java.util.Map<org.eclipse.core.runtime.IPath,org.eclipse.jdt.core.IClasspathEntry>, java.util.Map<org.eclipse.core.runtime.IPath,org.eclipse.jdt.core.IClasspathEntry>, org.eclipse.jdt.core.IJavaModelStatus, int, boolean) line: 1438	
	org.eclipse.jdt.internal.core.JavaProject.resolveClasspath(org.eclipse.jdt.internal.core.JavaModelManager$PerProjectInfo, boolean, boolean) line: 3329	
	org.eclipse.jdt.internal.core.ClasspathChange.generateDelta(org.eclipse.jdt.internal.core.JavaElementDelta, boolean) line: 245	
	org.eclipse.jdt.internal.core.DeltaProcessor.resourceChanged(org.eclipse.core.resources.IResourceChangeEvent) line: 2117	
	org.eclipse.jdt.internal.core.DeltaProcessingState.resourceChanged(org.eclipse.core.resources.IResourceChangeEvent) line: 490	
	org.eclipse.core.internal.events.NotificationManager$1.run() line: 321	
	org.eclipse.core.runtime.SafeRunner.run(org.eclipse.core.runtime.ISafeRunnable) line: 47	
	org.eclipse.core.internal.events.NotificationManager.notify(org.eclipse.core.internal.events.ResourceChangeListenerList$ListenerEntry[], org.eclipse.core.internal.events.ResourceChangeEvent, boolean) line: 311	
	org.eclipse.core.internal.events.NotificationManager.broadcastChanges(org.eclipse.core.internal.watson.ElementTree, org.eclipse.core.internal.events.ResourceChangeEvent, boolean) line: 174	
	org.eclipse.core.internal.resources.Workspace.broadcastPostChange() line: 465	
	org.eclipse.core.internal.resources.Workspace.endOperation(org.eclipse.core.runtime.jobs.ISchedulingRule, boolean) line: 1593	
	org.eclipse.core.internal.resources.Workspace.run(org.eclipse.core.runtime.ICoreRunnable, org.eclipse.core.runtime.jobs.ISchedulingRule, int, org.eclipse.core.runtime.IProgressMonitor) line: 2471	
	org.eclipse.core.internal.events.NotificationManager$NotifyJob.run(org.eclipse.core.runtime.IProgressMonitor) line: 60	
	org.eclipse.core.internal.jobs.Worker.run() line: 63	

running in parallel with

Thread [Worker-8: Updating Plug-in Classpaths] (Suspended)	
	waiting for: org.eclipse.jdt.internal.core.JavaModelManager$PerProjectInfo  (id=167)	
	org.eclipse.jdt.internal.core.JavaModelManager$PerProjectInfo.setResolvedClasspath(org.eclipse.jdt.core.IClasspathEntry[], org.eclipse.jdt.core.IClasspathEntry[], java.util.Map<org.eclipse.core.runtime.IPath,org.eclipse.jdt.core.IClasspathEntry>, java.util.Map<org.eclipse.core.runtime.IPath,org.eclipse.jdt.core.IClasspathEntry>, org.eclipse.jdt.core.IJavaModelStatus, int, boolean) line: 1436	
	org.eclipse.jdt.internal.core.JavaProject.resolveClasspath(org.eclipse.jdt.internal.core.JavaModelManager$PerProjectInfo, boolean, boolean) line: 3329	
	org.eclipse.jdt.internal.core.JavaProject.getResolvedClasspath() line: 2437	
	org.eclipse.jdt.internal.core.ExternalFolderChange.updateExternalFoldersIfNecessary(boolean, org.eclipse.core.runtime.IProgressMonitor) line: 40	
	org.eclipse.jdt.internal.core.SetClasspathOperation(org.eclipse.jdt.internal.core.ChangeClasspathOperation).classpathChanged(org.eclipse.jdt.internal.core.ClasspathChange, boolean) line: 63	
	org.eclipse.jdt.internal.core.SetClasspathOperation.executeOperation() line: 78	
	org.eclipse.jdt.internal.core.SetClasspathOperation(org.eclipse.jdt.internal.core.JavaModelOperation).run(org.eclipse.core.runtime.IProgressMonitor) line: 751	
	org.eclipse.core.internal.resources.Workspace.run(org.eclipse.core.runtime.ICoreRunnable, org.eclipse.core.runtime.jobs.ISchedulingRule, int, org.eclipse.core.runtime.IProgressMonitor) line: 2457	
	org.eclipse.core.internal.resources.Workspace.run(org.eclipse.core.resources.IWorkspaceRunnable, org.eclipse.core.runtime.jobs.ISchedulingRule, int, org.eclipse.core.runtime.IProgressMonitor) line: 2482	
	org.eclipse.jdt.internal.core.SetClasspathOperation(org.eclipse.jdt.internal.core.JavaModelOperation).runOperation(org.eclipse.core.runtime.IProgressMonitor) line: 821	
	org.eclipse.jdt.internal.core.JavaProject.setRawClasspath(org.eclipse.jdt.core.IClasspathEntry[], org.eclipse.jdt.core.IClasspathEntry[], org.eclipse.core.runtime.IPath, boolean, org.eclipse.core.runtime.IProgressMonitor) line: 3526	
	org.eclipse.jdt.internal.core.JavaProject.setRawClasspath(org.eclipse.jdt.core.IClasspathEntry[], org.eclipse.core.runtime.IPath, boolean, org.eclipse.core.runtime.IProgressMonitor) line: 3486	
	org.eclipse.jdt.internal.core.JavaProject.setRawClasspath(org.eclipse.jdt.core.IClasspathEntry[], org.eclipse.core.runtime.IProgressMonitor) line: 3542	
	org.eclipse.pde.internal.core.ClasspathComputer.setClasspath(org.eclipse.core.resources.IProject, org.eclipse.pde.core.plugin.IPluginModelBase) line: 70	
	org.eclipse.pde.internal.ui.wizards.tools.UpdateClasspathJob.updateClasspath(org.eclipse.pde.core.plugin.IPluginModelBase, org.eclipse.core.runtime.SubMonitor) line: 72	
	org.eclipse.pde.internal.ui.wizards.tools.UpdateClasspathJob$1.runInWorkspace(org.eclipse.core.runtime.IProgressMonitor) line: 47	
	org.eclipse.pde.internal.ui.wizards.tools.UpdateClasspathJob$1(org.eclipse.core.internal.resources.InternalWorkspaceJob).run(org.eclipse.core.runtime.IProgressMonitor) line: 43	
	org.eclipse.core.internal.jobs.Worker.run() line: 63	

jukzi added a commit to jukzi/eclipse.pde that referenced this issue Feb 5, 2025
Avoid setClasspath in NotifyJob concurrent to test execution

eclipse-pde#820
@jukzi jukzi linked a pull request Feb 5, 2025 that will close this issue
@jukzi
Copy link
Contributor

jukzi commented Feb 5, 2025

There are also 3 more jobs calling setClasspath concurrently:

Thread [Worker-2: Update Installed JREs] (Suspended (breakpoint at line 1406 in org.eclipse.jdt.internal.core.JavaModelManager$PerProjectInfo))	
	owns: org.eclipse.jdt.internal.core.JavaModelManager$PerProjectInfo  (id=168)	
	org.eclipse.jdt.internal.core.JavaModelManager$PerProjectInfo.setClasspath(org.eclipse.jdt.core.IClasspathEntry[], org.eclipse.jdt.core.IClasspathEntry[], org.eclipse.core.runtime.IPath, org.eclipse.jdt.core.IJavaModelStatus, org.eclipse.jdt.core.IClasspathEntry[], java.util.Map<org.eclipse.core.runtime.IPath,org.eclipse.jdt.core.IClasspathEntry>, java.util.Map<org.eclipse.core.runtime.IPath,org.eclipse.jdt.core.IClasspathEntry>, org.eclipse.jdt.core.IJavaModelStatus, boolean) line: 1406	
	org.eclipse.jdt.internal.core.JavaModelManager$PerProjectInfo.setResolvedClasspath(org.eclipse.jdt.core.IClasspathEntry[], org.eclipse.jdt.core.IClasspathEntry[], java.util.Map<org.eclipse.core.runtime.IPath,org.eclipse.jdt.core.IClasspathEntry>, java.util.Map<org.eclipse.core.runtime.IPath,org.eclipse.jdt.core.IClasspathEntry>, org.eclipse.jdt.core.IJavaModelStatus, int, boolean) line: 1438	
	org.eclipse.jdt.internal.core.JavaModelManager$PerProjectInfo.setResolvedClasspath(org.eclipse.jdt.core.IClasspathEntry[], java.util.Map<org.eclipse.core.runtime.IPath,org.eclipse.jdt.core.IClasspathEntry>, java.util.Map<org.eclipse.core.runtime.IPath,org.eclipse.jdt.core.IClasspathEntry>, org.eclipse.jdt.core.IJavaModelStatus, int, boolean) line: 1432	
	org.eclipse.jdt.internal.core.JavaModelManager$PerProjectInfo.resetResolvedClasspath() line: 1383	
	org.eclipse.jdt.internal.core.SetContainerOperation.executeOperation() line: 115	
	org.eclipse.jdt.internal.core.SetContainerOperation(org.eclipse.jdt.internal.core.JavaModelOperation).run(org.eclipse.core.runtime.IProgressMonitor) line: 751	
	org.eclipse.core.internal.resources.Workspace.run(org.eclipse.core.runtime.ICoreRunnable, org.eclipse.core.runtime.jobs.ISchedulingRule, int, org.eclipse.core.runtime.IProgressMonitor) line: 2457	
	org.eclipse.core.internal.resources.Workspace.run(org.eclipse.core.resources.IWorkspaceRunnable, org.eclipse.core.runtime.jobs.ISchedulingRule, int, org.eclipse.core.runtime.IProgressMonitor) line: 2482	
	org.eclipse.jdt.internal.core.SetContainerOperation(org.eclipse.jdt.internal.core.JavaModelOperation).runOperation(org.eclipse.core.runtime.IProgressMonitor) line: 821	
	org.eclipse.jdt.core.JavaCore.setClasspathContainer(org.eclipse.core.runtime.IPath, org.eclipse.jdt.core.IJavaProject[], org.eclipse.jdt.core.IClasspathContainer[], org.eclipse.core.runtime.IProgressMonitor) line: 6237	
	org.eclipse.jdt.internal.launching.JREContainerInitializer.initialize(org.eclipse.core.runtime.IPath, org.eclipse.jdt.core.IJavaProject[]) line: 114	
	org.eclipse.jdt.internal.launching.LaunchingPlugin$VMChanges.rebind(org.eclipse.core.runtime.IProgressMonitor, org.eclipse.jdt.core.IJavaProject[]) line: 379	
	org.eclipse.jdt.internal.launching.LaunchingPlugin$VMChanges$1.run(org.eclipse.core.runtime.IProgressMonitor) line: 299	
	org.eclipse.jdt.internal.core.BatchOperation.executeOperation() line: 41	
	org.eclipse.jdt.internal.core.BatchOperation(org.eclipse.jdt.internal.core.JavaModelOperation).run(org.eclipse.core.runtime.IProgressMonitor) line: 751	
	org.eclipse.core.internal.resources.Workspace.run(org.eclipse.core.runtime.ICoreRunnable, org.eclipse.core.runtime.jobs.ISchedulingRule, int, org.eclipse.core.runtime.IProgressMonitor) line: 2457	
	org.eclipse.core.internal.resources.Workspace.run(org.eclipse.core.resources.IWorkspaceRunnable, org.eclipse.core.runtime.jobs.ISchedulingRule, int, org.eclipse.core.runtime.IProgressMonitor) line: 2482	
	org.eclipse.jdt.core.JavaCore.run(org.eclipse.core.resources.IWorkspaceRunnable, org.eclipse.core.runtime.jobs.ISchedulingRule, org.eclipse.core.runtime.IProgressMonitor) line: 6106	
	org.eclipse.jdt.internal.launching.LaunchingPlugin$VMChanges.doit(org.eclipse.core.runtime.IProgressMonitor) line: 303	
	org.eclipse.jdt.internal.launching.LaunchingPlugin$JREUpdateJob.run(org.eclipse.core.runtime.IProgressMonitor) line: 400	
	org.eclipse.core.internal.jobs.Worker.run() line: 63	

and

Thread [Worker-5: Re-resolve Target state after VM-Install or EE change] (Suspended (breakpoint at line 1406 in org.eclipse.jdt.internal.core.JavaModelManager$PerProjectInfo))	
	owns: org.eclipse.jdt.internal.core.JavaModelManager$PerProjectInfo  (id=168)	
	org.eclipse.jdt.internal.core.JavaModelManager$PerProjectInfo.setClasspath(org.eclipse.jdt.core.IClasspathEntry[], org.eclipse.jdt.core.IClasspathEntry[], org.eclipse.core.runtime.IPath, org.eclipse.jdt.core.IJavaModelStatus, org.eclipse.jdt.core.IClasspathEntry[], java.util.Map<org.eclipse.core.runtime.IPath,org.eclipse.jdt.core.IClasspathEntry>, java.util.Map<org.eclipse.core.runtime.IPath,org.eclipse.jdt.core.IClasspathEntry>, org.eclipse.jdt.core.IJavaModelStatus, boolean) line: 1406	
	org.eclipse.jdt.internal.core.JavaModelManager$PerProjectInfo.setResolvedClasspath(org.eclipse.jdt.core.IClasspathEntry[], org.eclipse.jdt.core.IClasspathEntry[], java.util.Map<org.eclipse.core.runtime.IPath,org.eclipse.jdt.core.IClasspathEntry>, java.util.Map<org.eclipse.core.runtime.IPath,org.eclipse.jdt.core.IClasspathEntry>, org.eclipse.jdt.core.IJavaModelStatus, int, boolean) line: 1438	
	org.eclipse.jdt.internal.core.JavaProject.resolveClasspath(org.eclipse.jdt.internal.core.JavaModelManager$PerProjectInfo, boolean, boolean) line: 3329	
	org.eclipse.jdt.internal.core.JavaProject.getResolvedClasspath() line: 2437	
	org.eclipse.jdt.internal.core.DeltaProcessor.validateClasspaths(org.eclipse.core.resources.IResourceDelta) line: 2541	
	org.eclipse.jdt.internal.core.DeltaProcessor.resourceChanged(org.eclipse.core.resources.IResourceChangeEvent) line: 2169	
	org.eclipse.jdt.internal.core.DeltaProcessingState.resourceChanged(org.eclipse.core.resources.IResourceChangeEvent) line: 490	
	org.eclipse.core.internal.events.NotificationManager$1.run() line: 321	
	org.eclipse.core.runtime.SafeRunner.run(org.eclipse.core.runtime.ISafeRunnable) line: 47	
	org.eclipse.core.internal.events.NotificationManager.notify(org.eclipse.core.internal.events.ResourceChangeListenerList$ListenerEntry[], org.eclipse.core.internal.events.ResourceChangeEvent, boolean) line: 311	
	org.eclipse.core.internal.events.NotificationManager.broadcastChanges(org.eclipse.core.internal.watson.ElementTree, org.eclipse.core.internal.events.ResourceChangeEvent, boolean) line: 174	
	org.eclipse.core.internal.resources.Workspace.broadcastBuildEvent(java.lang.Object, int, int) line: 451	
	org.eclipse.core.internal.resources.Workspace.aboutToBuild(java.lang.Object, int) line: 394	
	org.eclipse.core.internal.resources.Project$1.run(org.eclipse.core.runtime.IProgressMonitor) line: 595	
	org.eclipse.core.internal.resources.Workspace.run(org.eclipse.core.runtime.ICoreRunnable, org.eclipse.core.runtime.jobs.ISchedulingRule, int, org.eclipse.core.runtime.IProgressMonitor) line: 2457	
	org.eclipse.core.internal.resources.Project.internalBuild(org.eclipse.core.resources.IBuildConfiguration, int, java.lang.String, java.util.Map<java.lang.String,java.lang.String>, org.eclipse.core.runtime.IProgressMonitor) line: 642	
	org.eclipse.core.internal.resources.Project.build(int, java.lang.String, java.util.Map<java.lang.String,java.lang.String>, org.eclipse.core.runtime.IProgressMonitor) line: 162	
	org.eclipse.pde.internal.core.MinimalState.reloadSystemPackagesIntoState() line: 342	
	org.eclipse.pde.internal.core.MinimalState$2.runInWorkspace(org.eclipse.core.runtime.IProgressMonitor) line: 314	
	org.eclipse.pde.internal.core.MinimalState$2(org.eclipse.core.internal.resources.InternalWorkspaceJob).run(org.eclipse.core.runtime.IProgressMonitor) line: 43	
	org.eclipse.core.internal.jobs.Worker.run() line: 63	

and

Thread [Worker-1: Decoration Calculation] (Suspended (breakpoint at line 1406 in org.eclipse.jdt.internal.core.JavaModelManager$PerProjectInfo))	
	owns: org.eclipse.jdt.internal.core.JavaModelManager$PerProjectInfo  (id=168)	
	org.eclipse.jdt.internal.core.JavaModelManager$PerProjectInfo.setClasspath(org.eclipse.jdt.core.IClasspathEntry[], org.eclipse.jdt.core.IClasspathEntry[], org.eclipse.core.runtime.IPath, org.eclipse.jdt.core.IJavaModelStatus, org.eclipse.jdt.core.IClasspathEntry[], java.util.Map<org.eclipse.core.runtime.IPath,org.eclipse.jdt.core.IClasspathEntry>, java.util.Map<org.eclipse.core.runtime.IPath,org.eclipse.jdt.core.IClasspathEntry>, org.eclipse.jdt.core.IJavaModelStatus, boolean) line: 1406	
	org.eclipse.jdt.internal.core.JavaModelManager$PerProjectInfo.setResolvedClasspath(org.eclipse.jdt.core.IClasspathEntry[], org.eclipse.jdt.core.IClasspathEntry[], java.util.Map<org.eclipse.core.runtime.IPath,org.eclipse.jdt.core.IClasspathEntry>, java.util.Map<org.eclipse.core.runtime.IPath,org.eclipse.jdt.core.IClasspathEntry>, org.eclipse.jdt.core.IJavaModelStatus, int, boolean) line: 1438	
	org.eclipse.jdt.internal.core.JavaProject.resolveClasspath(org.eclipse.jdt.internal.core.JavaModelManager$PerProjectInfo, boolean, boolean) line: 3329	
	org.eclipse.jdt.internal.core.JavaProject.getResolvedClasspath() line: 2437	
	org.eclipse.jdt.internal.core.JavaProject.findContainingClasspathEntry(org.eclipse.core.resources.IResource) line: 2724	
	org.eclipse.jdt.internal.core.JavaProject.isOnClasspath(org.eclipse.core.resources.IResource) line: 2708	
	org.eclipse.jdt.internal.ui.BuildpathIndicatorLabelDecorator.getOverlay(java.lang.Object) line: 49	
	org.eclipse.jdt.internal.ui.BuildpathIndicatorLabelDecorator.decorate(java.lang.Object, org.eclipse.jface.viewers.IDecoration) line: 35	
	org.eclipse.ui.internal.decorators.LightweightDecoratorDefinition.decorate(java.lang.Object, org.eclipse.jface.viewers.IDecoration) line: 254	
	org.eclipse.ui.internal.decorators.LightweightDecoratorManager$LightweightRunnable.run() line: 105	
	org.eclipse.core.runtime.SafeRunner.run(org.eclipse.core.runtime.ISafeRunnable) line: 47	
	org.eclipse.ui.internal.decorators.LightweightDecoratorManager.decorate(java.lang.Object, org.eclipse.ui.internal.decorators.DecorationBuilder, org.eclipse.ui.internal.decorators.LightweightDecoratorDefinition) line: 359	
	org.eclipse.ui.internal.decorators.LightweightDecoratorManager.getDecorations(java.lang.Object, org.eclipse.ui.internal.decorators.DecorationBuilder) line: 345	
	org.eclipse.ui.internal.decorators.DecorationScheduler$1.queue(java.lang.Object, boolean, org.eclipse.jface.viewers.IDecorationContext) line: 410	
	org.eclipse.ui.internal.decorators.DecorationScheduler$1.run(org.eclipse.core.runtime.IProgressMonitor) line: 388	
	org.eclipse.core.internal.jobs.Worker.run() line: 63	

@laeubi
Copy link
Contributor Author

laeubi commented Feb 5, 2025

See #820 (comment) where I described how you can capture jobs scheduled during execution of some method (e.g. record on test start and join before testing assertions).

@jukzi
Copy link
Contributor

jukzi commented Feb 5, 2025

Thanks, but i don't get how that should help against jobs that are already scheduled independent of the runnable. Also it seems to not to protect against deadlock due to jobs that reschedule themselves like Workbench Auto-Save Job, Periodic workspace save, Compacting resource model.

@laeubi
Copy link
Contributor Author

laeubi commented Feb 5, 2025

Thanks, but i don't get how that should help against jobs that are already scheduled independent of the runnable.

If they are not scheduled as part of the runnable then they are not caused by the calling code and then one would not need to wait for them.

Also it seems to not to protect against deadlock due to jobs that reschedule themselves

It just collects what jobs are scheduled (not sure why it should be a deadlock here), you can do whatever you want with this, e.g wait for a few seconds to join these, ignore them whatever you like.

@jukzi
Copy link
Contributor

jukzi commented Feb 5, 2025

i actually tried your idea with

	public static void joinAllScheduledJobs(ICoreRunnable runnable) throws CoreException {
		Set<Job> scheduledJobs = ConcurrentHashMap.newKeySet();
		IJobChangeListener listener = new JobChangeAdapter() {

			@Override
			public void scheduled(IJobChangeEvent event) {
				scheduledJobs.add(event.getJob());
			}

			@Override
			public void done(IJobChangeEvent event) {
				scheduledJobs.remove(event.getJob());
			}

		};
		Job.getJobManager().addJobChangeListener(listener);
		runnable.run(new NullProgressMonitor());
		Job.getJobManager().removeJobChangeListener(listener);
		for (Job job : scheduledJobs) {
			try {
				job.wakeUp();
				job.join();
			} catch (InterruptedException e) {
				Thread.currentThread().interrupt();
				return;
			}
		}
		return;
	}

Which deadlocks for example on BlockedJobsDialog$1 and does not join the independent scheduled jobs mentioned in #820 (comment) - which can interfere with the test!

@laeubi
Copy link
Contributor Author

laeubi commented Feb 5, 2025

I don't see why you want to wake up the job... and I would join with a timeout for this purpose. And of course it only works if not something is happen in the background randomly, as this is out of your control it can happen anytime so no way to "wait" for this and one maybe better use a WorkspaceJob to gather the information so you can make sure no other workspace actions run in parallel.

@jukzi
Copy link
Contributor

jukzi commented Feb 5, 2025

I don't see why you want to wake up the job.

to avoid joining a sleeping job

and I would join with a timeout for this purpose

Then i could equally just sleep a fixed time without complicated mechanism, because i know it will timeout

@laeubi
Copy link
Contributor Author

laeubi commented Feb 5, 2025

to avoid joining a sleeping job

If the job is sleeping then it should not run (yet) anyways and join will return immediately. The BlockedJobsDialog should only popup if something takes too long (and opens a blocking dialog) so if you force it to wake up earlier and then get a "deadlock" this is quite strange to me to complain about.

@jukzi
Copy link
Contributor

jukzi commented Feb 5, 2025

If the job is sleeping then it should not run (yet) anyways and join will return immediately.

nah, its scheduled with a delay and would run during the test, which is the task to avoid

@jukzi
Copy link
Contributor

jukzi commented Feb 5, 2025

I tried a lot waits now. Either the test is wrong or the functionality is broken:
When i wait long enough before and after setRawClasspath() in test_CreateFromScratch, then the test deterministically fails.

jukzi added a commit to jukzi/eclipse.pde that referenced this issue Feb 5, 2025
jukzi added a commit to jukzi/eclipse.pde that referenced this issue Feb 6, 2025
fixes random failing ClasspathUpdaterTest

When IJavaProject.setRawClasspath() is explicitly called with
ClasspathEntries distinct from PDE (like in the Test), and then later
PDEs UpdateClasspathJob is executed it can't compute the "oldEntry" and
fails with "... is not on its projects build path". The Message is
correct - it was manually removed from the projects build path. That
state should just be ignored so that PDE continues to set the
IClasspathEntries computed by PDE.

eclipse-pde#820
jukzi added a commit to jukzi/eclipse.pde that referenced this issue Feb 6, 2025
fixes random failing ClasspathUpdaterTest

When IJavaProject.setRawClasspath() is explicitly called with
ClasspathEntries distinct from PDE (like in the Test), and then later
PDEs UpdateClasspathJob is executed it can't compute the "oldEntry" and
fails with "... is not on its projects build path". The Message is
correct - it was manually removed from the projects build path. That
state should just be ignored so that PDE continues to set the
IClasspathEntries computed by PDE.

eclipse-pde#820
@jukzi jukzi linked a pull request Feb 6, 2025 that will close this issue
jukzi added a commit that referenced this issue Feb 6, 2025
fixes random failing ClasspathUpdaterTest

When IJavaProject.setRawClasspath() is explicitly called with
ClasspathEntries distinct from PDE (like in the Test), and then later
PDEs UpdateClasspathJob is executed it can't compute the "oldEntry" and
fails with "... is not on its projects build path". The Message is
correct - it was manually removed from the projects build path. That
state should just be ignored so that PDE continues to set the
IClasspathEntries computed by PDE.

#820
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
test Test case failure
Projects
None yet
2 participants