Fix race condition causing classes to be omitted from bundles in Gradle builds #6937
+9
−0
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Bnd workspace projects write both compiled classes and processed resources to the same output directory. Without explicit task ordering, Gradle can execute
compileJavaandprocessResourcesin parallel, allowing resource processing to overwrite compiled classes.Changes
mustRunAfterconstraints inBndPlugin.java:processResources.mustRunAfter(compileJava)for main source setprocessTestResources.mustRunAfter(compileTestJava)for test source setThis enforces execution order when both tasks run, preventing the race condition while preserving existing build semantics.
Scope
This fix addresses the race condition in Gradle builds only (affecting
target/gradle/classes). The issue has been reported to also occur in Eclipse builds (affectingtarget/classes), which use a different build system (Eclipse JDT) and are not addressed by this PR. Investigation into the Eclipse-specific issue is ongoing.Partially addresses #6896 (Gradle builds)
Original prompt
This section details on the original issue you should resolve
<issue_title>Bnd sometimes leaves classes out of bundles</issue_title>
<issue_description>This is a very odd one where I can see the symptoms but can't reproduce it consistently (thank goodness). I thought about reporting it earlier but decided to try investigating it myself first. However, that hasn't led anywhere.
I have a Bnd workspace containing many bundle projects. Their sources are laid out in the traditional Eclipse way with
javaclasses and other resources mixed together undersrc/. I'm not sure if that's important.They are all set up with these properties:
tool-modifier: ${if;${is;${driver};gradle};/gradle} target-dir: target src: src testsrc: unitTests/src bin: ${target-dir}${tool-modifier}/classes testbin: ${target-dir}${tool-modifier}/testClassesI sometimes use Eclipse, and sometimes Gradle. I've seen this bug in both.
Sometimes when I'm rebuilding the workspace, the build will stop with compile errors. When I investigate, I see that one of the earlier bundles has resources in it but no classes. If it has an activator, there's also a warning that the activator was not found in the bundle.
target/classes/ortarget/gradle/classes/(depending on the driver) only contains resources, but I can see that compilation took place, because there are usually some compiler warnings.If I delete
target/classes/(in Eclipse) or simply try the build again (in Gradle) it will usually build the bundle properly, but then I'll get the same problem with a different bundle.This usually continues until I perform the right combination of cleaning the workspace, stopping the Gradle daemon, restarting the IDE … I'm not sure. Then I might not see the problem again for a few days, but it has always come back.
CI builds use Gradle but I don't think I've seen this bug in one of those; I thought I had, then I found another problem with similar symptoms and worked around it. I suppose that since every CI build starts with a clean checkout, there isn't time for the problem to occur.
I can also consistently make the bug go away in Gradle by disabling all the
processResourcestasks. Then there are no resources in the bundles unless they are placed there by an-includeresource, but the classes are all present.My hypothesis is that the classes are indeed being written into the correct folder, but then they are somehow overwritten when the resources are copied in. I understand that Gradle or Eclipse, not Bnd, is handling the resources in this case. But I haven't seen a bug like this when I wasn't using Bnd, so I think Bnd must have something to do with it.
I tried writing a Python script that monitored the filesystem for new files and made them all read only, in the hopes of causing an error that would help me work out what was going on. It didn't work — either permissions don't work the way I hoped they would or something was making the files writable again before deleting them. However, I did see the script crash because a file whose permissions it was trying to change had already been deleted by the time it got round to doing that.
Gradle is using Bnd 7.1.0 with Gradle 8.14.3, but Eclipse is using a 7.2.0-SNAPSHOT build. I updated my Bndtools snapshot today, but haven't been doing the kind of work that would make the bug show up. I definitely saw it in an older snapshot from September.
I suppose I should try separating the Java sources from the resource files, and perhaps keep the Java sources under
src/but put the other files somewhere where Gradle wouldn't look for them. Then use-includeresourceto put them all in so that Bnd has full control of the process. (Would that make them bypass theclassesfolder?) But that's an invasive change I would rather not make at the moment.</issue_description><agent_instructions>Analyze the issue #6896 and the source code. If you think something needs to be fixed,please provide a PR.
Relevant code might be under
/gradle-plugins</agent_instructions>Comments on the Issue (you are @copilot in this section)
@chrisrueger Hmm my first reflex was to point you to https://bnd.bndtools.org/chapters/150-build.html#avoiding-target-dir-conflicts-between-different-build-tools and https://bnd.discourse.group/t/stop-gradle-from-stepping-on-eclipses-long-toes/295/11but it looks you are already using the driver to use different folders for each build tool.
But it sounds like two tools are stepping on each other's toes.
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.