[GRADLE-2896] Gradle hangs in project.exec when environment contains key as a GString Created: 25/Sep/13 Updated: 10/Feb/17 Resolved: 10/Feb/17 |
|
Status: | Resolved |
Project: | Gradle |
Affects Version/s: | None |
Fix Version/s: | None |
Type: | Bug | ||
Reporter: | Gradle Forums | Assignee: | Unassigned |
Resolution: | Won't Fix | Votes: | 0 |
Description |
I ran into this problem with more difficult build containing custom plugins, so I tried to narrow down the build script which is here class ExecCommand extends DefaultTask { @TaskAction ExecResult execResult = project.exec { ext.arch = 'x86' afterEvaluate { task showEnvironment(type: ExecCommand) I figured out that when I cast GString to String the hang disappears. task.environment = [(("JDK_HOME_${arch.toUpperCase()}").toString()) : jdkHome] It seems that Groovy doesn't convert the key of class GString into String when it is added into Map which is weird. I know Generics are de facto Objects, but groovy is weak typing language so I would expect implicit conversion. I monitored Gradle activity by Sysinternals ProcMon and command is not executed at all. I can also repro hang on Mac OS X, so it seems it is platform independent. I guess it might be some deadlock during evaluation of GString and accessing an extension. I also don't understand why there is a lazy evaluation of GString in effect. Note that when I put action into "simple" task I cannot repro it. I appreciate if someone can shed light on what's going on. Thanks, |
Comments |
Comment by Gradle Forums [ 25/Sep/13 ] |
I don't know why this makes the task hang. However, there is no way for Groovy to figure out that the keys are supposed to be Strings, and it's expected that you have to convert them yourself (if necessary). |
Comment by Gradle Forums [ 25/Sep/13 ] |
Peter, the usage of `GString` in Gradle is quite common and I am pointing out to hang of Gradle into which can any user easily get into. Shouldn't be the conversion to String enforced by `ExecSpec.environment()` methods? I spend some time to debug this problem. Here is an information about state and location of problem. The main thread executes the task in special thread in `org.gradle.internal.concurrent.DefaultExecutorFactory$StoppableExecutorImpl` runnable instance. The exception `ClassCastException` is thrown from the executed code so runnable instance ends its execution, but it leaves the main thread without notification it should leave the wait state. Here is the location from which is an exception thrown java.util.HashMap.putAll(HashMap.java:622) The exception is `ClassCastException` with description `org.codehaus.groovy.runtime.GStringImpl cannot be cast to java.lang.String`. It shows that there is a general problem here. If the code which is outside of try block in the `org.gradle.process.internal.ExecHandleRunner.run(ExecHandleRunner.java:64)` method throws an exception it causes the hang. It is catched here, but it is not logged or handled. org.gradle.internal.concurrent.DefaultExecutorFactory$StoppableExecutorImpl$1.run(DefaultExecutorFactory.java:68) The main thread hangs in this location sun.misc.Unsafe.park(Unsafe.java) |
Comment by Gradle Forums [ 25/Sep/13 ] |
Why is a `ClassCastException` thrown? Can you show that trace? |
Comment by Gradle Forums [ 25/Sep/13 ] |
Well it is thrown from method java.util.HashMap.putAll(HashMap.java:622) - see the first code listing above. I cannot provide deeper stack trace as I debug unmodified Gradle 1.7 release and logging of this exception is omitted in catch block. } catch (Throwable throwable) { To be honest I don't know how to gain the stack trace from the debugger. I just see an exception instance but stack trace cannot be expanded. However I try to modify and recompile Gradle sources to log this exception so we see the exact throw location. |
Comment by Gradle Forums [ 25/Sep/13 ] |
I have added the logging into catch block above so it is not under condition. Here is an exception stack trace. Failed to execute org.gradle.process.internal.ExecHandleRunner@69c41ba8. |
Comment by Gradle Forums [ 25/Sep/13 ] |
It seems that this issue is abandoned. Can be created a JIRA issue for this? I suppose I cannot create a JIRA isuue. The matter of the problem is that the Gradle swallows an exception here org.gradle.internal.concurrent.DefaultExecutorFactory$StoppableExecutorImpl$1.run ,the Runnable exits and the main thread is in infinite wait. As Gradle doesn't log an exception it requires big effort to figure out the root cause of problem (GString passed to java.lang.ProcessEnvironment$StringEnvironment). The problem is very easy reproducible even on other platforms without any change of script provided because execute is not performed. Thanks, |
Comment by Benjamin Muschko [ 15/Nov/16 ] |
As announced on the Gradle blog we are planning to completely migrate issues from JIRA to GitHub. We intend to prioritize issues that are actionable and impactful while working more closely with the community. Many of our JIRA issues are inactionable or irrelevant. We would like to request your help to ensure we can appropriately prioritize JIRA issues you’ve contributed to. Please confirm that you still advocate for your JIRA issue before December 10th, 2016 by:
We look forward to collaborating with you more closely on GitHub. Thank you for your contribution to Gradle! |
Comment by Benjamin Muschko [ 10/Feb/17 ] |
Thanks again for reporting this issue. We haven't heard back from you after our inquiry from November 15th. We are closing this issue now. Please create an issue on GitHub if you still feel passionate about getting it resolved. |