NationalSecurityAgency / ghidra

Ghidra is a software reverse engineering (SRE) framework
https://www.nsa.gov/ghidra
Apache License 2.0
50.53k stars 5.78k forks source link

parallel gradle build failure #6705

Open shuffle2 opened 2 months ago

shuffle2 commented 2 months ago

Describe the bug I have added org.gradle.parallel=true to gradle.properties. The cpu has 64 cores. Often, executing something like gradle assembleAll -x ip -x zipJavadocs fails with an error like:

The :Project:jar task failed.
Unable to delete file 'C:\src\ghidra\Ghidra\Framework\Project\build\libs\Project.jar'

where the falting .jar is nondeterministic (but always within Ghidra\Framework\Project\build\libs).

After looking at timeline of gradle build scan, it seemed like the jar target was always overlapping with a buildHelpFiles task.

After adding -x buildHelp to the gradle command line, the issue goes away. It seems there is some unsafe behavior going on with the buildHelp task or dependencies.

To Reproduce On machine with plenty of cores, run gradle --parallel assembleAll -x ip -x zipJavadocs.

Environment (please complete the following information):

-Gradle version: 8.8

dragonmacher commented 2 months ago

I scanned the helpProject.gradle looking for anything obvious that could cause this. So far all I'm seeing is the use of caching in the project. Specifically,

// This method contains logic for calculating help inputs based on the classpath of the project
// The work is cached, as the inputs may be requested multiple times during a build
ext.helpInputsCache = null
def getHelpInputs(Collection<File> fullClasspath) {

    if (ext.helpInputsCache != null) {
        return ext.helpInputsCache
    }

    def results = new HashSet<File>()
    Collection<File> modules = getMyModules(fullClasspath)
    modules.each { m -> 
        getHelpInputsFromModule(m.getAbsolutePath(), results)
    }

    // the classpath above does not include my module's contents, so add that manually
    def modulePath = file('.').getAbsolutePath()
    getHelpInputsFromModule(modulePath, results)

    ext.helpInputsCache = results.findAll(File::exists) 
    return ext.helpInputsCache
}

If the parallel grade mode is sharing the data structures in the ext space, then it is possible that multiple processes are attempting to build and use that cache. I'm not familiar enough with gradle to say for sure though.

astrelsky commented 2 months ago

4543 is unfortunately relevant

I have only encountered this a few times. Every time I have, simply deleting the file in question and trying again fixes it. Seems you knew this already.