-
Bug
-
Resolution: Unresolved
-
Minor
-
Jenkins 2.138.1
workflow-cps 2.57
workflow-cps-global-lib 2.12
When calling Collection.inject from a CPS-transformed method using a class field as the closure parameter, the closure gets called with a single list instead of the usual two parameters. This list contains the parameters that should have been used.
This doesn't happen when the calling method is marked @NonCPS or when the closure is a local variable (even a tiny wrapper calling the original class field). So there is an easy workaround, but I still think this is a bug.
Versions:
- Jenkins 2.138.1
- workflow-cps 2.57
- workflow-cps-global-lib 2.12
Example pipeline script:
class Test implements Serializable { def script Closure right = {l, e -> script.println "got l='$l', e='$e'"; l + e*10} Closure wrong = {script.println "got '$it'"; it[0] + it[1]*10} Test(script) { this.script = script } def testRight() { def x = [1,2,3].inject([], right) script.println x } @NonCPS def nonCPSRight() { def x = [1,2,3].inject([], right) script.println x } def localClosureRight() { Closure right = {l, e -> script.println "got l='$l', e='$e'"; l + e*10} def x = [1,2,3].inject([], right) script.println x } def localWrapperRight() { Closure cl = {l,e -> right.call(l,e)} def x = [1,2,3].inject([], cl) script.println x } def testWrong() { def x = [1,2,3].inject([], wrong) script.println x } } def t = new Test(this) println "--- wrong ---" t.testWrong() // this should not work, but does println "--- NonCPS right ---" t.nonCPSRight() // this works println "--- local closure right ---" t.localClosureRight() // this works println "--- local wrapper right ---" t.localWrapperRight() // this works println "--- right ---" t.testRight() // this fails
Build log:
[Pipeline] echo --- wrong --- [Pipeline] echo got '[[], 1]' [Pipeline] echo got '[[10], 2]' [Pipeline] echo got '[[10, 20], 3]' [Pipeline] echo [10, 20, 30] [Pipeline] echo --- NonCPS right --- [Pipeline] echo got l='[]', e='1' [Pipeline] echo got l='[10]', e='2' [Pipeline] echo got l='[10, 20]', e='3' [Pipeline] echo [10, 20, 30] [Pipeline] echo --- local closure right --- [Pipeline] echo got l='[]', e='1' [Pipeline] echo got l='[10]', e='2' [Pipeline] echo got l='[10, 20]', e='3' [Pipeline] echo [10, 20, 30] [Pipeline] echo --- local wrapper right --- [Pipeline] echo got l='[]', e='1' [Pipeline] echo got l='[10]', e='2' [Pipeline] echo got l='[10, 20]', e='3' [Pipeline] echo [10, 20, 30] [Pipeline] echo --- right --- [Pipeline] End of Pipeline hudson.remoting.ProxyException: groovy.lang.MissingMethodException: No signature of method: Test$_closure1.call() is applicable for argument types: ([Ljava.lang.Object;) values: [[[], 1]] Possible solutions: any(), any(), any(groovy.lang.Closure), use([Ljava.lang.Object;), each(groovy.lang.Closure), any(groovy.lang.Closure) at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:286) at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1022) at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:810) at groovy.lang.GroovyObjectSupport.invokeMethod(GroovyObjectSupport.java:46) at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:48) at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113) at com.cloudbees.groovy.cps.sandbox.DefaultInvoker.methodCall(DefaultInvoker.java:20) at com.cloudbees.groovy.cps.CpsDefaultGroovyMethods.inject(CpsDefaultGroovyMethods:5383) at com.cloudbees.groovy.cps.CpsDefaultGroovyMethods.inject(CpsDefaultGroovyMethods:5324) at Test.testRight(WorkflowScript:11) at WorkflowScript.run(WorkflowScript:49) at ___cps.transform___(Native Method) at com.cloudbees.groovy.cps.impl.ContinuationGroup.methodCall(ContinuationGroup.java:57) at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.dispatchOrArg(FunctionCallBlock.java:109) at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.fixArg(FunctionCallBlock.java:82) at sun.reflect.GeneratedMethodAccessor175.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at com.cloudbees.groovy.cps.impl.ContinuationPtr$ContinuationImpl.receive(ContinuationPtr.java:72) at com.cloudbees.groovy.cps.impl.LocalVariableBlock$LocalVariable.get(LocalVariableBlock.java:39) at com.cloudbees.groovy.cps.LValueBlock$GetAdapter.receive(LValueBlock.java:30) at com.cloudbees.groovy.cps.impl.LocalVariableBlock.evalLValue(LocalVariableBlock.java:28) at com.cloudbees.groovy.cps.LValueBlock$BlockImpl.eval(LValueBlock.java:55) at com.cloudbees.groovy.cps.LValueBlock.eval(LValueBlock.java:16) at com.cloudbees.groovy.cps.Next.step(Next.java:83) at com.cloudbees.groovy.cps.Continuable$1.call(Continuable.java:174) at com.cloudbees.groovy.cps.Continuable$1.call(Continuable.java:163) at org.codehaus.groovy.runtime.GroovyCategorySupport$ThreadCategoryInfo.use(GroovyCategorySupport.java:122) at org.codehaus.groovy.runtime.GroovyCategorySupport.use(GroovyCategorySupport.java:261) at com.cloudbees.groovy.cps.Continuable.run0(Continuable.java:163) at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.access$101(SandboxContinuable.java:34) at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.lambda$run0$0(SandboxContinuable.java:59) at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.GroovySandbox.runInSandbox(GroovySandbox.java:108) at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.run0(SandboxContinuable.java:58) at org.jenkinsci.plugins.workflow.cps.CpsThread.runNextChunk(CpsThread.java:182) at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.run(CpsThreadGroup.java:332) at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.access$200(CpsThreadGroup.java:83) at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:244) at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:232) at org.jenkinsci.plugins.workflow.cps.CpsVmExecutorService$2.call(CpsVmExecutorService.java:64) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at hudson.remoting.SingleLaneExecutorService$1.run(SingleLaneExecutorService.java:131) at jenkins.util.ContextResettingExecutorService$1.run(ContextResettingExecutorService.java:28) at jenkins.security.ImpersonatingExecutorService$1.run(ImpersonatingExecutorService.java:59) 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:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748)