Details
-
Bug
-
Status: Closed
-
Major
-
Resolution: Fixed
-
2.4.10
-
None
-
None
-
Gradle 3.5
Description
I just upgraded our Gradle build from 1.12 (including Groovy 1.8.6) to 3.5 (including Groovy 2.4.10).
Now I get a very strange behavior for stuff that is there for years already and it looks to me as if this is a Groovy bug, maybe a non-threadsafeness of Closures.
I have a custom task that contains the following code:
def sourceFilesSize = getSourceFiles().files.size() def poolSize = Runtime.runtime.availableProcessors() def executor = new ThreadPoolExecutor(poolSize, poolSize, 0, SECONDS, new ArrayBlockingQueue<Runnable>([sourceFilesSize, 1].max())) def tasks = [] inputs.outOfDate { toTransform -> tasks.add executor.submit { project.exec { if (gscPath) { // here starts com.empic.build.tasks.Ghostscript$_exec_closure8$_closure11 environment 'GSC', gscPath def tempDir = "$temporaryDir/${Thread.currentThread().name}" project.file(tempDir).mkdirs() environment 'TEMP', tempDir } executable executablePath def arguments = [toTransform.file.absolutePath] if ((sourceFilesSize == 1) && getDestinationFile()) { arguments << getDestinationFile().absolutePath } else if (destinationDirectory) { arguments << new File(destinationDirectory, fileNameMapping(toTransform.file.name)).absolutePath } else { arguments << new File(toTransform.file.parentFile, fileNameMapping(toTransform.file.name)).absolutePath } args arguments // here ends com.empic.build.tasks.Ghostscript$_exec_closure8$_closure11 } } } executor.shutdown() executor.awaitTermination 1, HOURS tasks*.get() // here is line 137
When this task is executed e. g. with five source files, sometimes all works fine, sometime the build fails with
... Caused by: java.util.concurrent.ExecutionException: java.lang.IllegalStateException: initialize must be called for meta class of class com.empic.build.tasks.Ghostscript$_exec_closure8$_closure11(class org.codehaus.groovy.runtime.metaclass.ClosureMetaClass) to complete initialisation process before any invocation or field/property access can be done at com.empic.build.tasks.Ghostscript.exec(Ghostscript.groovy:137) at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:73) ... 80 more Caused by: java.lang.IllegalStateException: initialize must be called for meta class of class com.empic.build.tasks.Ghostscript$_exec_closure8$_closure11(class org.codehaus.groovy.runtime.metaclass.ClosureMetaClass) to complete initialisation process before any invocation or field/property access can be done
Actually I was not able to reproduce the problem locally, but if I run the build on our CI server and attach a debugger, I indeed was able to reproduce the problem with a relatively high reproduction rate. (as in every second to third build approximately, opposed to once every 100 builds)
I logged the current thread when the initialized property is set to true and when it is requested with non-suspending breakpoints, but this seems to have caused the timing to change enough already that I was not able to reproduce the error within approximately the first two dozens of tries.
I was able to successfully break at the throwing of the IllegalStateException though. This happens in groovy.lang.MetaClassImpl.checkInitalised.
The stacktrace at this point is:
"pool-2-thread-3@10709" prio=5 tid=0x47 nid=NA runnable java.lang.Thread.State: RUNNABLE at groovy.lang.MetaClassImpl.checkInitalised(MetaClassImpl.java:1647) at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:257) at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1027) at groovy.lang.Closure.call(Closure.java:414) at groovy.lang.Closure.call(Closure.java:408) at groovy.lang.Closure.run(Closure.java:495) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:745)
with the closure for which we are at the ClosureMetaClass in the topmost frame being the mentioned com.empic.build.tasks.Ghostscript$_exec_closure8$_closure11.
Attachments
Issue Links
- is a clone of
-
GROOVY-8213 Closures are maybe not Threadsafe
- Closed