Moved into Pipeline: Groovy Plugin. See jenkinsci/workflow-cps-plugin#612.
cloudbees / groovy-cps Goto Github PK
View Code? Open in Web Editor NEWGroovy execution in the continuation passing style
License: Apache License 2.0
Groovy execution in the continuation passing style
License: Apache License 2.0
Moved into Pipeline: Groovy Plugin. See jenkinsci/workflow-cps-plugin#612.
@NonCPS
and @CompileStatic
are not compatible (and possibly not @TypeChecked
)--very weird errors start showing up if they're combined. If the @NonCPS
processor finds that its method is affected by @CompileStatic
, it should throw an error instead of trying to compile and producing unintuitive downstream errors.
It's silly to hand-code CpsDefaultGroovyMethods
by manually doing CPS transformation.
It'd save me a lot of typing if I can apply CpsTransformer
during the build process of groovy-cps itself. This way, all I need to do is to cut&paste method definitions from Groovy's DefaultGroovyMethods
that has Closure
in the signature.
Coming from jenkinsci/JenkinsPipelineUnit#426
Groovy 2.4.12
com.lesfurets.jenkins.TestSerializationCPS > testSerialization FAILED
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
file:/Users/dblock/source/JenkinsPipelineUnit/dblock/src/test/jenkins/job/serializeCPS.jenkins: -1: Annotation @com.cloudbees.groovy.cps.WorkflowTransformed has RUNTIME retention and 2 occurrences. Duplicate annotations not allowed.
@ line -1, column -1.
1 error
Groovy 2.4.13
java.lang.annotation.AnnotationFormatError: Duplicate annotation for class: interface com.cloudbees.groovy.cps.WorkflowTransformed: @com.cloudbees.groovy.cps.WorkflowTransformed()
at java.base/sun.reflect.annotation.AnnotationParser.parseAnnotations2(AnnotationParser.java:126)
Error goes away in Groovy 2.4.14, but it could still be a duplicate annotation (didn't debug).
Declaring an interface breaks CPS compilation, this prevents basic OOP design in scripts
interface Strategy {
Closure process(Object event)
}
return true
java.lang.NullPointerException: Cannot invoke method visit() on null object
at org.codehaus.groovy.runtime.NullObject.invokeMethod(NullObject.java:77)
at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:45)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:42)
at org.codehaus.groovy.runtime.callsite.NullCallSite.call(NullCallSite.java:32)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:42)
at org.codehaus.groovy.ast.stmt.BlockStatement$visit.call(Unknown Source)
at com.cloudbees.groovy.cps.CpsTransformer.visitMethod(CpsTransformer.groovy:166)
at sun.reflect.GeneratedMethodAccessor12.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:361)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:903)
at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(PogoMetaClassSite.java:66)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:141)
at com.cloudbees.groovy.cps.CpsTransformer$_call_closure1.doCall(CpsTransformer.groovy:95)
at sun.reflect.GeneratedMethodAccessor11.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:272)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:903)
at groovy.lang.Closure.call(Closure.java:415)
at groovy.lang.Closure.call(Closure.java:428)
at org.codehaus.groovy.runtime.DefaultGroovyMethods.each(DefaultGroovyMethods.java:1379)
at org.codehaus.groovy.runtime.DefaultGroovyMethods.each(DefaultGroovyMethods.java:1351)
at org.codehaus.groovy.runtime.DefaultGroovyMethods$each.call(Unknown Source)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:42)
at org.codehaus.groovy.runtime.DefaultGroovyMethods$each.call(Unknown Source)
at com.cloudbees.groovy.cps.CpsDefaultGroovyMethods.each(CpsDefaultGroovyMethods.groovy:26)
at sun.reflect.GeneratedMethodAccessor25.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.codehaus.groovy.runtime.metaclass.ReflectionMetaMethod.invoke(ReflectionMetaMethod.java:51)
at org.codehaus.groovy.runtime.metaclass.NewInstanceMetaMethod.invoke(NewInstanceMetaMethod.java:54)
at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoMetaMethodSiteNoUnwrapNoCoerce.invoke(PojoMetaMethodSite.java:271)
at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:53)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callSafe(AbstractCallSite.java:82)
at com.cloudbees.groovy.cps.CpsTransformer.call(CpsTransformer.groovy:95)
at org.codehaus.groovy.control.CompilationUnit.applyToPrimaryClassNodes(CompilationUnit.java:970)
at org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:548)
at org.codehaus.groovy.control.CompilationUnit.processPhaseOperations(CompilationUnit.java:526)
at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:503)
at groovy.lang.GroovyClassLoader.doParseClass(GroovyClassLoader.java:302)
at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:281)
at groovy.lang.GroovyShell.parseClass(GroovyShell.java:731)
at groovy.lang.GroovyShell.parse(GroovyShell.java:743)
at groovy.lang.GroovyShell.parse(GroovyShell.java:770)
at groovy.lang.GroovyShell.parse(GroovyShell.java:761)
at groovy.lang.GroovyShell$parse.call(Unknown Source)
If the interface is empty, the exception is slightly different:
interface Empty {}
return true
Script1.groovy: -1: The field '__timeStamp' is not 'public static final' but is defined in interface 'Empty'.
@ line -1, column -1.
1 error
at org.codehaus.groovy.control.ErrorCollector.failIfErrors(ErrorCollector.java:302)
at org.codehaus.groovy.control.CompilationUnit.applyToPrimaryClassNodes(CompilationUnit.java:997)
at org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:548)
at org.codehaus.groovy.control.CompilationUnit.processPhaseOperations(CompilationUnit.java:526)
at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:503)
at groovy.lang.GroovyClassLoader.doParseClass(GroovyClassLoader.java:302)
at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:281)
at groovy.lang.GroovyShell.parseClass(GroovyShell.java:731)
at groovy.lang.GroovyShell.parse(GroovyShell.java:743)
at groovy.lang.GroovyShell.parse(GroovyShell.java:770)
at groovy.lang.GroovyShell.parse(GroovyShell.java:761)
at groovy.lang.GroovyShell$parse.call(Unknown Source)
During testing of the shared libraries it's really useful to be able to intercept the calls.
All the current implementations of the Jenkins Shared Libraries unit tests are quite useless - there are a number of issues impossible to test outside of actual workflow-cps-plugin. We have the next issue about that: JENKINS-33925.
The following construct does not as expected work under CPS as the closure gets a null
argument:
diff --git a/src/test/groovy/com/cloudbees/groovy/cps/CpsTransformerTest.groovy b/src/test/groovy/com/cloudbees/groovy/cps/CpsTransformerTest.groovy
index 9f45611..249f919 100644
--- a/src/test/groovy/com/cloudbees/groovy/cps/CpsTransformerTest.groovy
+++ b/src/test/groovy/com/cloudbees/groovy/cps/CpsTransformerTest.groovy
@@ -367,6 +367,14 @@ class CpsTransformerTest extends AbstractGroovyCpsTest {
}
@Test
+ void gstringClosureStringWriter() {
+ assert evalCPS('''
+ def x = "foo";
+ return "${ w -> w << x }".toString();
+''') == "foo";
+ }
+
+ @Test
void ternaryOp() {
assert evalCPS('''
return true ? 5 : null.makeCall();
And throws the following NullPointerException
:
gstringClosureStringWriter(com.cloudbees.groovy.cps.CpsTransformerTest) Time elapsed: 0.014 sec <<< ERROR!
java.lang.NullPointerException: Cannot invoke method leftShift() on null object
at org.codehaus.groovy.runtime.NullObject.invokeMethod(NullObject.java:77)
at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:45)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:42)
at org.codehaus.groovy.runtime.callsite.NullCallSite.call(NullCallSite.java:32)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:42)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
at com.cloudbees.groovy.cps.sandbox.DefaultInvoker.methodCall(DefaultInvoker.java:15)
at Script1.run(Script1.groovy:3)
at Script1.run(Script1.groovy:3)
at ___cps.transform___(Native Method)
at com.cloudbees.groovy.cps.impl.ContinuationGroup.methodCall(ContinuationGroup.java:69)
at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.dispatchOrArg(FunctionCallBlock.java:106)
at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.fixArg(FunctionCallBlock.java:79)
at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.cloudbees.groovy.cps.impl.ContinuationPtr$ContinuationImpl.receive(ContinuationPtr.java:72)
at com.cloudbees.groovy.cps.impl.LocalVariableBlock$LocalVariable.get(LocalVariableBlock.java:33)
at com.cloudbees.groovy.cps.LValueBlock$GetAdapter.receive(LValueBlock.java:30)
at com.cloudbees.groovy.cps.impl.LocalVariableBlock.evalLValue(LocalVariableBlock.java:22)
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:58)
at com.cloudbees.groovy.cps.Next.run(Next.java:49)
at com.cloudbees.groovy.cps.Next$run.call(Unknown Source)
at com.cloudbees.groovy.cps.AbstractGroovyCpsTest.evalCPSonly(AbstractGroovyCpsTest.groovy:55)
at com.cloudbees.groovy.cps.AbstractGroovyCpsTest.evalCPS(AbstractGroovyCpsTest.groovy:49)
at com.cloudbees.groovy.cps.AbstractGroovyCpsTest$evalCPS.callCurrent(Unknown Source)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:46)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:141)
at com.cloudbees.groovy.cps.CpsTransformerTest.gstringClosureStringWriter(CpsTransformerTest.groovy:371)
There's no way to limit the depth of recursive calls, it just consumes ever-increasing memory as the depth grows.
The automatic conversion of field access to getter calls means that the following common lazy-loading pattern translates to an unbounded recursive call that will bring down a Jenkins master:
def something = null
def getSomething() {
if (something == null) {
return "someComplexComputationResult;"
}
}
def stuff = getSomething();
We need a way to limit the depth of the recursion to prevent this scenario and handle appropriately (error out or at least pause execution and force the issue to be addressed).
I did not find the exact reason or circumstances for this to happen, but I managed to create a test case showing the behaviour:
@Test
void nonCPSCallsCPSMethod() {
evalCPS('''
class Foo {
int count
@NonCPS
static Foo create(int value) {
def aList = [5,6,7,8].collect { new Foo(count: it) }
return aList.find { it.matches(value) }
}
boolean matches(int value) {
count == value
}
}
Foo.create(7)
''')
}
This fails in the evalCPS
test method. The CPS version returns a Boolean, while the NonCPS version correctly returns a Foo instance.
Of course, a NonCPS method calling a CPS method might be considered questionable, but in that case at least the compiliation and/or the execution should fail with a meaningful exception.
Hello.
The following test is failing when I clone & run mvn test
in this repo,
with Java 1.8.0_40 and Groovy 2.4.8 : https://github.com/cloudbees/groovy-cps/blob/master/src/test/groovy/com/cloudbees/groovy/cps/AbstractGroovyCpsTest.groovy#L50
Tests run: 46, Failures: 1, Errors: 0, Skipped: 2, Time elapsed: 3.561 sec <<< FAILURE!
each(com.cloudbees.groovy.cps.CpsTransformerTest) Time elapsed: 0.031 sec <<< FAILURE!
Assertion failed:
assert v==sh.evaluate(script)
|| | | |
0| | 55
| | def x = 0;
| | (0..10).each { y -> x+=y; }
| | return x;
| groovy.lang.GroovyShell@37ddb69a
false
at org.codehaus.groovy.runtime.InvokerHelper.assertFailed(InvokerHelper.java:386)
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.assertFailed(ScriptBytecodeAdapter.java:658)
at com.cloudbees.groovy.cps.AbstractGroovyCpsTest.evalCPS(AbstractGroovyCpsTest.groovy:50)
at com.cloudbees.groovy.cps.AbstractGroovyCpsTest$evalCPS.callCurrent(Unknown Source)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:46)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:141)
at com.cloudbees.groovy.cps.CpsTransformerTest.each(CpsTransformerTest.groovy:407)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:252)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:141)
at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:112)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:189)
at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:165)
at org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:85)
at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:115)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:75)
Also, what do you think about adding enabling Travis CI tests for thir repo ?
We do regularly face above issue in one of our pipelines.
Could you please have a look at #104
When transforming an abstract class with abstract methods
abstract class Parent {
abstract void run()
}
This leads to a Nullpointer Exception:
BUG! exception in phase 'semantic analysis' in source unit 'WorkflowScript' exception in phase 'canonicalization' in source unit 'file:/d:/jenkins/jobs/GitTest/jobs/RC-Build/builds/39/libs/PipelineLibrary/src/com/gfk/st2/build/pipeline/pipeline/Pipeline.groovy' unexpected NullpointerException
at org.codehaus.groovy.control.CompilationUnit.applyToPrimaryClassNodes(CompilationUnit.java:1058)
at org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:591)
at org.codehaus.groovy.control.CompilationUnit.processPhaseOperations(CompilationUnit.java:569)
at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:546)
at groovy.lang.GroovyClassLoader.doParseClass(GroovyClassLoader.java:298)
at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:268)
at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:254)
at groovy.lang.GroovyClassLoader.recompile(GroovyClassLoader.java:761)
at groovy.lang.GroovyClassLoader.loadClass(GroovyClassLoader.java:718)
at groovy.lang.GroovyClassLoader.loadClass(GroovyClassLoader.java:787)
at java.lang.ClassLoader.loadClass(Unknown Source)
at groovy.lang.GroovyClassLoader.loadClass(GroovyClassLoader.java:677)
at groovy.lang.GroovyClassLoader.loadClass(GroovyClassLoader.java:545)
at org.codehaus.groovy.control.ClassNodeResolver.tryAsLoaderClassOrScript(ClassNodeResolver.java:185)
at org.codehaus.groovy.control.ClassNodeResolver.findClassNode(ClassNodeResolver.java:170)
at org.codehaus.groovy.control.ClassNodeResolver.resolveName(ClassNodeResolver.java:126)
at org.codehaus.groovy.control.ResolveVisitor.resolveToOuter(ResolveVisitor.java:676)
at org.codehaus.groovy.control.ResolveVisitor.resolve(ResolveVisitor.java:308)
at org.codehaus.groovy.control.ResolveVisitor.resolveFromModule(ResolveVisitor.java:638)
at org.codehaus.groovy.control.ResolveVisitor.resolve(ResolveVisitor.java:308)
at org.codehaus.groovy.control.ResolveVisitor.resolve(ResolveVisitor.java:276)
at org.codehaus.groovy.control.ResolveVisitor.resolveOrFail(ResolveVisitor.java:260)
at org.codehaus.groovy.control.ResolveVisitor.resolveOrFail(ResolveVisitor.java:272)
at org.codehaus.groovy.control.ResolveVisitor.transformConstructorCallExpression(ResolveVisitor.java:1047)
at org.codehaus.groovy.control.ResolveVisitor.transform(ResolveVisitor.java:706)
at org.codehaus.groovy.ast.ClassCodeExpressionTransformer.visitExpressionStatement(ClassCodeExpressionTransformer.java:142)
at org.codehaus.groovy.ast.stmt.ExpressionStatement.visit(ExpressionStatement.java:42)
at org.codehaus.groovy.ast.CodeVisitorSupport.visitBlockStatement(CodeVisitorSupport.java:37)
at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitBlockStatement(ClassCodeVisitorSupport.java:166)
at org.codehaus.groovy.control.ResolveVisitor.visitBlockStatement(ResolveVisitor.java:1318)
at org.codehaus.groovy.ast.stmt.BlockStatement.visit(BlockStatement.java:71)
at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitClassCodeContainer(ClassCodeVisitorSupport.java:104)
at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitConstructorOrMethod(ClassCodeVisitorSupport.java:115)
at org.codehaus.groovy.ast.ClassCodeExpressionTransformer.visitConstructorOrMethod(ClassCodeExpressionTransformer.java:53)
at org.codehaus.groovy.control.ResolveVisitor.visitConstructorOrMethod(ResolveVisitor.java:201)
at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitMethod(ClassCodeVisitorSupport.java:126)
at org.codehaus.groovy.ast.ClassNode.visitContents(ClassNode.java:1078)
at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitClass(ClassCodeVisitorSupport.java:53)
at org.codehaus.groovy.control.ResolveVisitor.visitClass(ResolveVisitor.java:1261)
at org.codehaus.groovy.control.ResolveVisitor.startResolving(ResolveVisitor.java:176)
at org.codehaus.groovy.control.CompilationUnit$11.call(CompilationUnit.java:651)
at org.codehaus.groovy.control.CompilationUnit.applyToSourceUnits(CompilationUnit.java:931)
at org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:593)
at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:542)
at groovy.lang.GroovyClassLoader.doParseClass(GroovyClassLoader.java:298)
at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:268)
at groovy.lang.GroovyShell.parseClass(GroovyShell.java:688)
at groovy.lang.GroovyShell.parse(GroovyShell.java:700)
at org.jenkinsci.plugins.workflow.cps.CpsGroovyShell.reparse(CpsGroovyShell.java:67)
at org.jenkinsci.plugins.workflow.cps.CpsFlowExecution.parseScript(CpsFlowExecution.java:411)
at org.jenkinsci.plugins.workflow.cps.CpsFlowExecution.start(CpsFlowExecution.java:374)
at org.jenkinsci.plugins.workflow.job.WorkflowRun.run(WorkflowRun.java:220)
at hudson.model.ResourceController.execute(ResourceController.java:98)
at hudson.model.Executor.run(Executor.java:404)
Caused by: java.lang.NullPointerException: Cannot get property 'lineNumber' on null object
at org.codehaus.groovy.runtime.NullObject.getProperty(NullObject.java:60)
at org.codehaus.groovy.runtime.InvokerHelper.getProperty(InvokerHelper.java:172)
at org.codehaus.groovy.runtime.callsite.NullCallSite.getProperty(NullCallSite.java:47)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callGetProperty(AbstractCallSite.java:296)
at com.cloudbees.groovy.cps.CpsTransformer.loc(CpsTransformer.groovy:351)
at sun.reflect.GeneratedMethodAccessor63.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325)
at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:384)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1024)
at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(PogoMetaClassSite.java:69)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:166)
at com.cloudbees.groovy.cps.CpsTransformer$_visitWithSafepoint_closure6_closure49_closure50.doCall(CpsTransformer.groovy:292)
at sun.reflect.GeneratedMethodAccessor157.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325)
at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:294)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1024)
at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(PogoMetaClassSite.java:69)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:166)
at com.cloudbees.groovy.cps.CpsTransformer$_visitWithSafepoint_closure6_closure49_closure50.doCall(CpsTransformer.groovy)
at sun.reflect.GeneratedMethodAccessor156.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325)
at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:294)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1024)
at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:42)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:57)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:117)
at com.cloudbees.groovy.cps.CpsTransformer.makeChildren(CpsTransformer.groovy:336)
at sun.reflect.GeneratedMethodAccessor62.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoCachedMethodSiteNoUnwrapNoCoerce.invoke(PogoMetaMethodSite.java:210)
at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.callCurrent(PogoMetaMethodSite.java:59)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:52)
at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.callCurrent(PogoMetaMethodSite.java:64)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:166)
at com.cloudbees.groovy.cps.CpsTransformer.makeNode(CpsTransformer.groovy:311)
at sun.reflect.GeneratedMethodAccessor61.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325)
at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:384)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1024)
at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(PogoMetaClassSite.java:69)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:174)
at com.cloudbees.groovy.cps.CpsTransformer$_visitWithSafepoint_closure6_closure49.doCall(CpsTransformer.groovy:291)
at sun.reflect.GeneratedMethodAccessor155.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325)
at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:294)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1024)
at groovy.lang.Closure.call(Closure.java:414)
at groovy.lang.Closure.call(Closure.java:430)
at org.codehaus.groovy.runtime.DefaultGroovyMethods.each(DefaultGroovyMethods.java:2030)
This happens because visitMethod()
tries to parse the statements of the method, which are clearly null.
This could be easily solved by enhancing CpsTransformer.shouldBeTransformed()
with a check for abstractness.
I will provide a PR for this.
The following script does not executes as expected as the speak()
call cannot be resolved against the Script instance:
class MyStrategy {
Closure<String> process() {
return {
speak()
}
}
}
String speak() {
'from Script instance'
}
Closure<String> closure = new MyStrategy().process()
closure.rehydrate(this, this, this).call()
The resolution is done against the original scope:
groovy.lang.MissingMethodException: No signature of method: MyStrategy.speak() is applicable for argument types: () values: []
Possible solutions: split(groovy.lang.Closure), sleep(long), sleep(long, groovy.lang.Closure), inspect(), every(), grep()
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:55)
at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:51)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:42)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
at com.cloudbees.groovy.cps.sandbox.DefaultInvoker.methodCall(DefaultInvoker.java:15)
at MyStrategy.process(Script1.groovy:5)
at Script1.run(Script1.groovy:13)
at ___cps.transform___(Native Method)
at com.cloudbees.groovy.cps.impl.ContinuationGroup.methodCall(ContinuationGroup.java:48)
at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.dispatchOrArg(FunctionCallBlock.java:106)
at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.fixName(FunctionCallBlock.java:74)
at sun.reflect.GeneratedMethodAccessor4.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.ConstantBlock.eval(ConstantBlock.java:21)
at com.cloudbees.groovy.cps.Next.step(Next.java:58)
at com.cloudbees.groovy.cps.Next.run(Next.java:49)
at com.cloudbees.groovy.cps.Next$run.call(Unknown Source)
at com.cloudbees.groovy.cps.AbstractGroovyCpsTest.evalCPSonly(AbstractGroovyCpsTest.groovy:55)
at com.cloudbees.groovy.cps.AbstractGroovyCpsTest.evalCPS(AbstractGroovyCpsTest.groovy:49)
at com.cloudbees.groovy.cps.AbstractGroovyCpsTest$evalCPS.callCurrent(Unknown Source)
Maybe a consequence of #12 (incomplete type checking), CPS does not support constructor list:
http://groovy-lang.org/semantics.html#_list_and_map_constructors
In addition to the assignment rules above, if an assignment is deemed invalid, in type checked mode, a list literal or a map literal A can be assigned to a variable of type T if:
the assignment is a variable declaration and A is a list literal and T has a constructor whose parameters match the types of the elements in the list literal
assert evalCPS('''\
File f = ['/parent', 'name']
return f
'''.stripIndent()) == new File('/parent', 'name')
The CPS execution return value is actually the List
instance not being converted to a proper File
:
Assertion failed:
assert resultInCps==sh.evaluate(script)
| | | | |
| | | | File f = ['/parent', 'name']
| | | | return f
| | | \parent\name
| | groovy.lang.GroovyShell@14a002b1
| false
[/parent, name]
Hello,
Following the introduction of a new warning log message in version 2.7.1 of the Pipeline:Groovy plugin, we are now receiving types of the following warning in builds using the Artifactory Plugin:
expected to call org.jfrog.hudson.pipeline.common.types.ArtifactoryServer.upload but wound up catching artifactoryUpload
The pipeline API supported by the Artifactory plugin creates objects, on which methods can be invoked.
For example:
def server = Artifactory.server 'my-server'
server.upload ...
Notice that the 'server' object allows executing the 'artifactoryUpload' step.
This OOP style is very convenient and allows reusing code and configuration. This approach received very positive feedbacks since it was introduced.
Currently however, this is achieved by having the 'server' instance store the CpsScript, so that it can be used to invoke the step (by using ‘cpsScript.invokeMethod').
The Artifactory pipeline API is available for a few years already and has become extremely popular.
We would appreciate your advice on how to change the plugin in a way that will both satisfy the CPS guidelines without breaking its current functionality and structure.
Thank you
Hey Team,
I've been getting CPS errors when trying to use @CompileStatic
at the class level. When I move the attribute to each method, the transformation succeeds.
I'd like to add @CompileStatic
to all compatible classes, but it's a bit inconvenient to add the attribute to every method. Especially my Unit Test classes.
Let me know if I'm using this incorrectly, or if it's not worth using on a CPS transformed class.
The following code does work without transformation:
import groovy.transform.InheritConstructors
abstract class Parent {
abstract String getName()
}
class Child extends Parent {
String name
int getLength() {
return name.length()
}
}
@InheritConstructors
class GC extends Child {
}
assert new GC(name: 'hallo').getLength() == 5
However, when tranforming it results in:
groovy.lang.MissingFieldException: No such field: name for class: GC
|tat groovy.lang.MetaClassImpl.getAttribute(MetaClassImpl.java:2518)
|tat groovy.lang.MetaClassImpl.getAttribute(MetaClassImpl.java:3351)
|tat org.codehaus.groovy.runtime.InvokerHelper.getAttribute(InvokerHelper.java:129)
|tat org.codehaus.groovy.runtime.ScriptBytecodeAdapter.getField(ScriptBytecodeAdapter.java:302)
|tat com.cloudbees.groovy.cps.sandbox.DefaultInvoker.getAttribute(DefaultInvoker.java:42)
|tat com.cloudbees.groovy.cps.impl.AttributeAccessBlock.rawGet(AttributeAccessBlock.java:20)
|tat Child.getLength(Script1.groovy:12)
|tat Script1.run(Script1.groovy:20)
|tat ___cps.transform___(Native Method)
|tat com.cloudbees.groovy.cps.impl.PropertyishBlock$ContinuationImpl.get(PropertyishBlock.java:74)
|tat com.cloudbees.groovy.cps.LValueBlock$GetAdapter.receive(LValueBlock.java:30)
|tat com.cloudbees.groovy.cps.impl.PropertyishBlock$ContinuationImpl.fixName(PropertyishBlock.java:66)
|tat sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
|tat sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
|tat sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
|tat java.lang.reflect.Method.invoke(Method.java:498)
|tat com.cloudbees.groovy.cps.impl.ContinuationPtr$ContinuationImpl.receive(ContinuationPtr.java:72)
|tat com.cloudbees.groovy.cps.impl.ConstantBlock.eval(ConstantBlock.java:21)
|tat com.cloudbees.groovy.cps.Next.step(Next.java:74)
|tat com.cloudbees.groovy.cps.Next.run(Next.java:65)
|tat com.cloudbees.groovy.cps.Next$run.call(Unknown Source)
|tat org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:42)
|tat org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
|tat org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)
|tat com.cloudbees.groovy.cps.AbstractGroovyCpsTest.evalCPSonly(AbstractGroovyCpsTest.groovy:55)
|tat com.cloudbees.groovy.cps.AbstractGroovyCpsTest.evalCPS(AbstractGroovyCpsTest.groovy:49)
|tat com.cloudbees.groovy.cps.AbstractGroovyCpsTest$evalCPS.callCurrent(Unknown Source)
|tat org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:46)
|tat org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133)
|tat org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:141)
|tat com.cloudbees.groovy.cps.CpsTransformerTest.nonCPSCallsCPSMethod(CpsTransformerTest.groovy:768)
|tat sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
|tat sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
|tat sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
|tat java.lang.reflect.Method.invoke(Method.java:498)
|tat org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
|tat org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
|tat org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
|tat org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
|tat org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
|tat org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
|tat org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
|tat org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
|tat org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
|tat org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
|tat org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
|tat org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
|tat org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
|tat org.junit.runners.ParentRunner.run(ParentRunner.java:309)
|tat org.junit.runner.JUnitCore.run(JUnitCore.java:160)
|tat com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
|tat com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
|tat com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
|tat com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
When replacing the assert with:
assert new Child(name: 'hallo').getLength() == 5
it works though.
Sequence.each
correctly dispatches to CpsDefaultGroovyMethods.each
, but somehow ArrayList.each
isn't dispatching to that method. Instead, it finds DefaultGroovyMethods.each
.
Presumably the way we register CpsDefaultGroovyMethods
methods into Groovy runtime is incorrect, and the method dispatch cache for ArrayList
contains stale entry.
To fix this issue, either figure out how to insert meta-method into Groovy, or figure out how to clean up stale cache.
CPS transformation ignores the declared return type of function, and always treat as if it is typed as Object
.
This creates a behaviour difference between normal Groovy code vs CPS-transformed code.
int foo() { return "abc" }
foo(); // compiles fine but at runtime throws ClassCastException
void bar() { 42; }
x=bar(); // runs fine but assigns null
This should be relatively easy by having Continuation check the type of the value (or substitute it by null in case of void
methods)
Hi, I am working on the simpletravisrunner plugin and I have something like this:
class SimpleTravisRunner implements Serializable {
[...]
public void call(String path, String labelExpr = null, Integer timeout = 50, scm = null) {
[...]
script.node(label) {
TravisScriptExecutorFactory executorFactory = new TravisScriptExecutorFactory()
TravisScriptExecutor executor = executorFactory.getExecutorInstance(script, travisSteps)
executor.loadData()
executor.execute()
}
}
private SimpleTravisRunner getSimpleTravisRunner() {
return this
}
interface TravisScriptExecutor {
public void loadData()
public void execute()
}
class TravisScriptExecutorFactory implements Serializable {
private static final def executorsMap = [
generic: GenericTravisScriptExecutor,
go: LanguageGoEnvironment,
]
TravisScriptExecutorFactory() {}
TravisScriptExecutor getExecutorInstance(CpsScript script, Map<String, Object> travisYml) {
TravisScriptExecutor executor = null
if (travisYml.containsKey("language") && executorsMap.containsKey(travisYml.get("language"))) {
executor = executorsMap \
.get(travisYml.get("language")) \
.newInstance(getSimpleTravisRunner(), script, travisYml)
} else {
executor = executorsMap \
.get("generic") \
.newInstance(getSimpleTravisRunner(), script, travisYml)
}
return executor
}
}
class GenericTravisScriptExecutor implements TravisScriptExecutor, Serializable {
[...]
GenericTravisScriptExecutor(CpsScript script, Map<String, Object> travisYml) {
this.script = script
this.travisYml = travisYml
}
[...]
void loadData() {
envMatrix = new TravisEnvMatrix(defaultEnv, script)
if (travisYml.containsKey("env")) {
generateEnvMatrix(travisYml.get("env"), envMatrix)
}
}
[...]
void execute() {
[...]
}
[...]
}
class LanguageGoEnvironment extends GenericTravisScriptExecutor {
[...]
LanguageGoEnvironment(CpsScript script, Map<String, Object> travisYml) {
super(script, travisYml)
}
[...]
@Override
void loadData() {
super.loadData() // Code fails here.
[...]
}
@Override
void execute() {
script.dir(projPath) {
super.loadData()
}
}
[...]
}
}
I left in this code the relevant parts. It fails with this message:
hudson.remoting.ProxyException: org.codehaus.groovy.runtime.InvokerInvocationException: groovy.lang.MissingMethodException: No signature of method: org.jenkinsci.plugins.simpletravisrunner.SimpleTravisRunner.loadData() is applicable for argument types: () values: []
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:97)
at groovy.lang.MetaClassImpl.invokeMissingMethod(MetaClassImpl.java:830)
at groovy.lang.MetaClassImpl.invokePropertyOrMissing(MetaClassImpl.java:1128)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1081)
at com.cloudbees.groovy.cps.sandbox.DefaultInvoker.superCall(DefaultInvoker.java:29)
at org.jenkinsci.plugins.simpletravisrunner.SimpleTravisRunner$LanguageGoEnvironment.loadData(jar:file:/var/jenkins_home/plugins/simple-travis-runner/WEB-INF/lib/simple-travis-runner.jar!/org/jenkinsci/plugins/simpletravisrunner/SimpleTravisRunner.groovy:564)
at org.jenkinsci.plugins.simpletravisrunner.SimpleTravisRunner.call(jar:file:/var/jenkins_home/plugins/simple-travis-runner/WEB-INF/lib/simple-travis-runner.jar!/org/jenkinsci/plugins/simpletravisrunner/SimpleTravisRunner.groovy:108)
at ___cps.transform___(Native Method)
at com.cloudbees.groovy.cps.impl.ContinuationGroup.methodCall(ContinuationGroup.java:54)
at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.dispatchOrArg(FunctionCallBlock.java:109)
at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.fixName(FunctionCallBlock.java:77)
at sun.reflect.GeneratedMethodAccessor244.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.ConstantBlock.eval(ConstantBlock.java:21)
at com.cloudbees.groovy.cps.Next.step(Next.java:58)
at com.cloudbees.groovy.cps.Continuable.run0(Continuable.java:154)
at org.jenkinsci.plugins.workflow.cps.CpsThread.runNextChunk(CpsThread.java:163)
at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.run(CpsThreadGroup.java:324)
at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.access$100(CpsThreadGroup.java:78)
at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:236)
at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:224)
at org.jenkinsci.plugins.workflow.cps.CpsVmExecutorService$2.call(CpsVmExecutorService.java:63)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at hudson.remoting.SingleLaneExecutorService$1.run(SingleLaneExecutorService.java:112)
at jenkins.util.ContextResettingExecutorService$1.run(ContextResettingExecutorService.java:28)
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)
Caused by: hudson.remoting.ProxyException: groovy.lang.MissingMethodException: No signature of method: org.jenkinsci.plugins.simpletravisrunner.SimpleTravisRunner.loadData() is applicable for argument types: () values: []
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:55)
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.invokeMethodOnCurrentN(ScriptBytecodeAdapter.java:91)
at org.jenkinsci.plugins.simpletravisrunner.SimpleTravisRunner.this$dist$invoke$1(SimpleTravisRunner.groovy)
at org.jenkinsci.plugins.simpletravisrunner.SimpleTravisRunner$LanguageGoEnvironment.methodMissing(SimpleTravisRunner.groovy)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
at groovy.lang.MetaClassImpl.invokeMissingMethod(MetaClassImpl.java:830)
at groovy.lang.MetaClassImpl.invokePropertyOrMissing(MetaClassImpl.java:1128)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1081)
at com.cloudbees.groovy.cps.sandbox.DefaultInvoker.superCall(DefaultInvoker.java:29)
... 24 more
The thing is that the super.loadData()
(from LanguageGoStrategy.loadData()
) is trying to call SimpleTravisRunner.loadData()
, the outer class, instead of GenericTravisScriptExecutor.loadData()
, the super class. But the super constructor call is working fine.
CPS basics /doc/cps-basics.md seems to use for normal manner recursive function.
Will in example shown the normal-manner function factorial not recur infinitely?
Recursion seems in general to be advanced topic of programming languages. Why do CPS Basics need to use such edge-case example?
Why can't CPS Basics not use more straight forward normal-manner example, example free of recursion yet other advanced programming concepts? Is CPS possibly intended to solve problems only of advanced programming concepts?
Used example raises same or higher number of questions as number of those it solves. Reader can't learn from CPS Basics as they get confronted with open points yet before story talk really starts.
CallEnv carries a 'types' array around for every instance:
private Map<String, Class> types = new HashMap<String, Class>();
The FunctionCallEnv and BlockScopeEnv and ClosureCallEnv all carry around their own independent maps of locals:
private final Map<String,Object> locals = new HashMap<String, Object>();
These maps can in aggregate be memory consuming - we should make an effort to reduce the memory footprint of CPS code by trying to remove duplication where possible and use compact maps where we can (singletonMap, emptyMap, etc).
When writing support classes for pipeline plugins, it's very easy to accidentally forget to apply @NonCPS
to a method and end up with weird errors. Like @CompileStatic
, @NonCPS
should also be applicable to a whole type to treat every method as non-CPS.
The following does not work under CPS as the up()
method cannot be resolved:
diff --git a/src/test/groovy/com/cloudbees/groovy/cps/CpsTransformerTest.groovy b/src/test/groovy/com/cloudbees/groovy/cps/CpsTransformerTest.groovy
index 9f45611..5bf85d0 100644
--- a/src/test/groovy/com/cloudbees/groovy/cps/CpsTransformerTest.groovy
+++ b/src/test/groovy/com/cloudbees/groovy/cps/CpsTransformerTest.groovy
@@ -535,4 +535,18 @@ class CpsTransformerTest extends AbstractGroovyCpsTest {
assert evalCPS("('2009' ==~ /\\d+/) as boolean")
assert !evalCPS("('holla' ==~ /\\d+/) as boolean")
}
+
+ @Test
+ void category() {
+ assert evalCPS('''
+ class BarCategory {
+ static String up(String text) {
+ text.toUpperCase()
+ }
+ }
+ return use(BarCategory) {
+ 'foo'.up()
+ };
+''') == 'FOO';
+ }
}
category(com.cloudbees.groovy.cps.CpsTransformerTest) Time elapsed: 0.027 sec <<< ERROR!
groovy.lang.MissingMethodException: No signature of method: java.lang.String.up() is applicable for argument types: () values: []
Possible solutions: dump(), use([Ljava.lang.Object;), is(java.lang.Object), use(java.lang.Class, groovy.lang.Closure), tr(java.lang.String, java.lang.String), tr(java.lang.CharSequence, java.lang.CharSequence)
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:55)
at org.codehaus.groovy.runtime.callsite.PojoMetaClassSite.call(PojoMetaClassSite.java:46)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:42)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
at com.cloudbees.groovy.cps.sandbox.DefaultInvoker.methodCall(DefaultInvoker.java:15)
at Script1.run(Script1.groovy:8)
at Script1.run(Script1.groovy:7)
at ___cps.transform___(Native Method)
at com.cloudbees.groovy.cps.impl.ContinuationGroup.methodCall(ContinuationGroup.java:69)
at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.dispatchOrArg(FunctionCallBlock.java:106)
at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.fixName(FunctionCallBlock.java:74)
at sun.reflect.GeneratedMethodAccessor4.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.cloudbees.groovy.cps.impl.ContinuationPtr$ContinuationImpl.receive(ContinuationPtr.java:72)
at com.cloudbees.groovy.cps.impl.ConstantBlock.eval(ConstantBlock.java:21)
at com.cloudbees.groovy.cps.Next.step(Next.java:58)
at com.cloudbees.groovy.cps.Next.run(Next.java:49)
at com.cloudbees.groovy.cps.Next$run.call(Unknown Source)
at com.cloudbees.groovy.cps.AbstractGroovyCpsTest.evalCPSonly(AbstractGroovyCpsTest.groovy:55)
at com.cloudbees.groovy.cps.AbstractGroovyCpsTest.evalCPS(AbstractGroovyCpsTest.groovy:49)
at com.cloudbees.groovy.cps.AbstractGroovyCpsTest$evalCPS.callCurrent(Unknown Source)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:46)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:141)
at com.cloudbees.groovy.cps.CpsTransformerTest.category(CpsTransformerTest.groovy:541)
I have a custom step, listed in its entirety below. The return value is explicitly specified as boolean
, and I'm returning a boolean expression, but CPS turns the return into an Integer
(0/1), which then causes failures downstream (since the sandbox won't coerce back to a boolean).
@NonCPS
boolean call(String remote = UPSTREAM_REMOTE, String branch = UPSTREAM_BRANCH) {
def retVal = sh returnStatus: true, script: "git merge-base --is-ancestor HEAD $remote/$branch"
return (retVal == 0)
}
When using a GString
to resolve a method pointer, I am getting the below CCE:
java.lang.ClassCastException: org.codehaus.groovy.runtime.GStringImpl cannot be cast to java.lang.String
at com.cloudbees.groovy.cps.impl.MethodPointerBlock$ContinuationImpl.done(MethodPointerBlock.java:68)
at sun.reflect.GeneratedMethodAccessor3870.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at com.cloudbees.groovy.cps.impl.ContinuationPtr$ContinuationImpl.receive(ContinuationPtr.java:72)
at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.dispatchOrArg(FunctionCallBlock.java:103)
at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.fixArg(FunctionCallBlock.java:82)
at sun.reflect.GeneratedMethodAccessor209.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at com.cloudbees.groovy.cps.impl.ContinuationPtr$ContinuationImpl.receive(ContinuationPtr.java:72)
at WorkflowScript.run(WorkflowScript:50)
at ___cps.transform___(Native Method)
at com.cloudbees.groovy.cps.impl.ContinuationGroup.methodCall(ContinuationGroup.java:60)
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.GeneratedMethodAccessor209.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at com.cloudbees.groovy.cps.impl.ContinuationPtr$ContinuationImpl.receive(ContinuationPtr.java:72)
at com.cloudbees.groovy.cps.impl.ConstantBlock.eval(ConstantBlock.java:21)
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:174)
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(Unknown Source)
at hudson.remoting.SingleLaneExecutorService$1.run(SingleLaneExecutorService.java:112)
at jenkins.util.ContextResettingExecutorService$1.run(ContextResettingExecutorService.java:28)
at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
at java.util.concurrent.FutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Finished: FAILURE
To reproduce, all you need to do is to get a pointer using the obj.&"$method_name"
syntax, e.g., if you have a vars/test.groovy that looks like this:
def msg() {
echo "Hello!"
}
try the below from Jenkinsfile
:
def action = 'msg'
def c = test.&"$action"
c()
As a workaround, I was able to call toString()
on the GString
, so for the above code to work, change it to def c = test.&("$action.toString())"
Seems very similar to #105
Seen in a declarative Jenkins pipeline that uses parallel stages. The issue is not reproducible, but transient and happens once in a while.
23:02:03 an exception which occurred:
23:02:03 in field com.cloudbees.groovy.cps.impl.ForInLoopBlock$ContinuationImpl.itr
23:02:03 in object com.cloudbees.groovy.cps.impl.ForInLoopBlock$ContinuationImpl@fa00c69
23:02:03 in field com.cloudbees.groovy.cps.impl.ContinuationPtr$ContinuationImpl.target
23:02:03 in object com.cloudbees.groovy.cps.impl.ContinuationPtr$ContinuationImpl@de9259b
23:02:03 in field com.cloudbees.groovy.cps.impl.LoopBlockScopeEnv.continue_
23:02:03 in object com.cloudbees.groovy.cps.impl.LoopBlockScopeEnv@32cc355d
23:02:03 in field com.cloudbees.groovy.cps.impl.ProxyEnv.parent
23:02:03 in object com.cloudbees.groovy.cps.impl.BlockScopeEnv@1310e23a
23:02:03 in field com.cloudbees.groovy.cps.impl.CallEnv.caller
23:02:03 in object com.cloudbees.groovy.cps.impl.FunctionCallEnv@7e3705bf
23:02:03 in field com.cloudbees.groovy.cps.Continuable.e
23:02:03 in object org.jenkinsci.plugins.workflow.cps.SandboxContinuable@150491f0
23:02:03 in field org.jenkinsci.plugins.workflow.cps.CpsThread.program
23:02:03 in object org.jenkinsci.plugins.workflow.cps.CpsThread@5d77bcdc
23:02:03 in field org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.threads
23:02:03 in object org.jenkinsci.plugins.workflow.cps.CpsThreadGroup@7babc0ed
23:02:03 in object org.jenkinsci.plugins.workflow.cps.CpsThreadGroup@7babc0ed
23:02:03 Also: an exception which occurred:
23:02:03 in field com.cloudbees.groovy.cps.impl.ForInLoopBlock$ContinuationImpl.itr
23:02:03 in object com.cloudbees.groovy.cps.impl.ForInLoopBlock$ContinuationImpl@fa00c69
23:02:03 in field com.cloudbees.groovy.cps.impl.ContinuationPtr$ContinuationImpl.target
23:02:03 in object com.cloudbees.groovy.cps.impl.ContinuationPtr$ContinuationImpl@de9259b
23:02:03 in field com.cloudbees.groovy.cps.impl.LoopBlockScopeEnv.continue_
23:02:03 in object com.cloudbees.groovy.cps.impl.LoopBlockScopeEnv@32cc355d
23:02:03 in field com.cloudbees.groovy.cps.impl.ProxyEnv.parent
23:02:03 in object com.cloudbees.groovy.cps.impl.BlockScopeEnv@3d77650f
23:02:03 in field com.cloudbees.groovy.cps.impl.CallEnv.caller
23:02:03 in object com.cloudbees.groovy.cps.impl.FunctionCallEnv@4efb1727
23:02:03 in field com.cloudbees.groovy.cps.Continuable.e
23:02:03 in object org.jenkinsci.plugins.workflow.cps.SandboxContinuable@150491f0
23:02:03 in field org.jenkinsci.plugins.workflow.cps.CpsThread.program
23:02:03 in object org.jenkinsci.plugins.workflow.cps.CpsThread@5d77bcdc
23:02:03 in field org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.threads
23:02:03 in object org.jenkinsci.plugins.workflow.cps.CpsThreadGroup@7babc0ed
23:02:03 in object org.jenkinsci.plugins.workflow.cps.CpsThreadGroup@7babc0ed
23:02:03 Caused: java.io.NotSerializableException: java.util.Spliterators$1Adapter
23:02:03 Also: org.jenkinsci.plugins.workflow.steps.FlowInterruptedException
23:02:03 at org.jenkinsci.plugins.workflow.cps.CpsBodyExecution.cancel(CpsBodyExecution.java:253)
23:02:03 at org.jenkinsci.plugins.workflow.cps.steps.ParallelStepExecution.stop(ParallelStepExecution.java:74)
23:02:03 at org.jenkinsci.plugins.workflow.cps.steps.ParallelStep$ResultHandler$Callback.checkAllDone(ParallelStep.java:151)
23:02:03 at org.jenkinsci.plugins.workflow.cps.steps.ParallelStep$ResultHandler$Callback.onFailure(ParallelStep.java:138)
23:02:03 at org.jenkinsci.plugins.workflow.cps.CpsBodyExecution$FailureAdapter.receive(CpsBodyExecution.java:361)
23:02:03 at com.cloudbees.groovy.cps.impl.ThrowBlock$1.receive(ThrowBlock.java:68)
23:02:03 at com.cloudbees.groovy.cps.impl.ConstantBlock.eval(ConstantBlock.java:21)
23:02:03 at com.cloudbees.groovy.cps.Next.step(Next.java:83)
23:02:03 at com.cloudbees.groovy.cps.Continuable$1.call(Continuable.java:174)
23:02:03 at com.cloudbees.groovy.cps.Continuable$1.call(Continuable.java:163)
23:02:03 at org.codehaus.groovy.runtime.GroovyCategorySupport$ThreadCategoryInfo.use(GroovyCategorySupport.java:129)
23:02:03 at org.codehaus.groovy.runtime.GroovyCategorySupport.use(GroovyCategorySupport.java:268)
23:02:03 at com.cloudbees.groovy.cps.Continuable.run0(Continuable.java:163)
23:02:03 at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.access$001(SandboxContinuable.java:18)
23:02:03 at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.run0(SandboxContinuable.java:51)
23:02:03 at org.jenkinsci.plugins.workflow.cps.CpsThread.runNextChunk(CpsThread.java:185)
23:02:03 at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.run(CpsThreadGroup.java:400)
23:02:03 at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.access$400(CpsThreadGroup.java:96)
23:02:03 at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:312)
23:02:03 at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:276)
23:02:03 at org.jenkinsci.plugins.workflow.cps.CpsVmExecutorService$2.call(CpsVmExecutorService.java:67)
23:02:03 Also: org.jenkinsci.plugins.workflow.steps.FlowInterruptedException
23:02:03 at org.jenkinsci.plugins.workflow.cps.CpsBodyExecution.cancel(CpsBodyExecution.java:253)
23:02:03 at org.jenkinsci.plugins.workflow.cps.steps.ParallelStepExecution.stop(ParallelStepExecution.java:74)
23:02:03 at org.jenkinsci.plugins.workflow.cps.steps.ParallelStep$ResultHandler$Callback.checkAllDone(ParallelStep.java:151)
23:02:03 at org.jenkinsci.plugins.workflow.cps.steps.ParallelStep$ResultHandler$Callback.onFailure(ParallelStep.java:138)
23:02:03 at org.jenkinsci.plugins.workflow.cps.CpsBodyExecution$FailureAdapter.receive(CpsBodyExecution.java:361)
23:02:03 at com.cloudbees.groovy.cps.impl.ThrowBlock$1.receive(ThrowBlock.java:68)
23:02:03 at com.cloudbees.groovy.cps.impl.ConstantBlock.eval(ConstantBlock.java:21)
23:02:03 at com.cloudbees.groovy.cps.Next.step(Next.java:83)
23:02:03 at com.cloudbees.groovy.cps.Continuable$1.call(Continuable.java:174)
23:02:03 at com.cloudbees.groovy.cps.Continuable$1.call(Continuable.java:163)
23:02:03 at org.codehaus.groovy.runtime.GroovyCategorySupport$ThreadCategoryInfo.use(GroovyCategorySupport.java:129)
23:02:03 at org.codehaus.groovy.runtime.GroovyCategorySupport.use(GroovyCategorySupport.java:268)
23:02:03 at com.cloudbees.groovy.cps.Continuable.run0(Continuable.java:163)
23:02:03 at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.access$001(SandboxContinuable.java:18)
23:02:03 at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.run0(SandboxContinuable.java:51)
23:02:03 at org.jenkinsci.plugins.workflow.cps.CpsThread.runNextChunk(CpsThread.java:185)
23:02:03 at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.run(CpsThreadGroup.java:400)
23:02:03 at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.access$400(CpsThreadGroup.java:96)
23:02:03 at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:312)
23:02:03 at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:276)
23:02:03 at org.jenkinsci.plugins.workflow.cps.CpsVmExecutorService$2.call(CpsVmExecutorService.java:67)
23:02:03 Caused: java.io.NotSerializableException: java.util.Spliterators$1Adapter
23:02:03 at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:926)
23:02:03 at org.jboss.marshalling.river.RiverMarshaller.doWriteFields(RiverMarshaller.java:1082)
23:02:03 at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:1040)
23:02:03 at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:920)
23:02:03 at org.jboss.marshalling.river.RiverMarshaller.doWriteFields(RiverMarshaller.java:1082)
23:02:03 at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:1040)
23:02:03 at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:920)
23:02:03 at org.jboss.marshalling.river.RiverMarshaller.doWriteFields(RiverMarshaller.java:1082)
23:02:03 at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:1040)
23:02:03 at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:920)
23:02:03 at org.jboss.marshalling.river.RiverMarshaller.doWriteFields(RiverMarshaller.java:1082)
23:02:03 at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:1040)
23:02:03 at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:1019)
23:02:03 at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:920)
23:02:03 at org.jboss.marshalling.river.RiverMarshaller.doWriteFields(RiverMarshaller.java:1082)
23:02:03 at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:1040)
23:02:03 at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:1019)
23:02:03 at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:920)
23:02:03 at org.jboss.marshalling.river.RiverMarshaller.doWriteFields(RiverMarshaller.java:1082)
23:02:03 at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:1040)
23:02:03 at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:1019)
23:02:03 at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:920)
23:02:03 at org.jboss.marshalling.river.RiverMarshaller.doWriteFields(RiverMarshaller.java:1082)
23:02:03 at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:1040)
23:02:03 at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:920)
23:02:03 at org.jboss.marshalling.river.BlockMarshaller.doWriteObject(BlockMarshaller.java:65)
23:02:03 at org.jboss.marshalling.river.BlockMarshaller.writeObject(BlockMarshaller.java:56)
23:02:03 at org.jboss.marshalling.MarshallerObjectOutputStream.writeObjectOverride(MarshallerObjectOutputStream.java:50)
23:02:03 at org.jboss.marshalling.river.RiverObjectOutputStream.writeObjectOverride(RiverObjectOutputStream.java:179)
23:02:03 at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:344)
23:02:03 at java.util.concurrent.ConcurrentSkipListMap.writeObject(ConcurrentSkipListMap.java:1437)
23:02:03 at sun.reflect.GeneratedMethodAccessor291.invoke(Unknown Source)
23:02:03 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
23:02:03 at java.lang.reflect.Method.invoke(Method.java:498)
23:02:03 at org.jboss.marshalling.reflect.JDKSpecific$SerMethods.callWriteObject(JDKSpecific.java:156)
23:02:03 at org.jboss.marshalling.reflect.SerializableClass.callWriteObject(SerializableClass.java:191)
23:02:03 at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:1028)
23:02:03 at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:920)
23:02:03 at org.jboss.marshalling.river.RiverMarshaller.doWriteFields(RiverMarshaller.java:1082)
23:02:03 at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:1040)
23:02:03 at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:920)
23:02:03 at org.jboss.marshalling.AbstractObjectOutput.writeObject(AbstractObjectOutput.java:58)
23:02:03 at org.jboss.marshalling.AbstractMarshaller.writeObject(AbstractMarshaller.java:111)
23:02:03 at org.jenkinsci.plugins.workflow.support.pickles.serialization.RiverWriter.lambda$writeObject$0(RiverWriter.java:144)
23:02:03 at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.GroovySandbox.runInSandbox(GroovySandbox.java:237)
23:02:03 at org.jenkinsci.plugins.workflow.support.pickles.serialization.RiverWriter.writeObject(RiverWriter.java:143)
23:02:03 at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.saveProgram(CpsThreadGroup.java:553)
23:02:03 at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.saveProgram(CpsThreadGroup.java:530)
23:02:03 at org.jenkinsci.plugins.workflow.cps.CpsStepContext$3.onSuccess(CpsStepContext.java:555)
23:02:03 at org.jenkinsci.plugins.workflow.cps.CpsStepContext$3.onSuccess(CpsStepContext.java:549)
23:02:03 at org.jenkinsci.plugins.workflow.cps.CpsFlowExecution$4$1.run(CpsFlowExecution.java:917)
23:02:03 at org.jenkinsci.plugins.workflow.cps.CpsVmExecutorService$1.run(CpsVmExecutorService.java:38)
23:02:03 at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
23:02:03 at java.util.concurrent.FutureTask.run(FutureTask.java:266)
23:02:03 at hudson.remoting.SingleLaneExecutorService$1.run(SingleLaneExecutorService.java:136)
23:02:03 at jenkins.util.ContextResettingExecutorService$1.run(ContextResettingExecutorService.java:28)
23:02:03 at jenkins.security.ImpersonatingExecutorService$1.run(ImpersonatingExecutorService.java:59)
23:02:03 at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
23:02:03 at java.util.concurrent.FutureTask.run(FutureTask.java:266)
23:02:03 at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
23:02:03 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
23:02:03 at java.lang.Thread.run(Thread.java:748)
Given an arbitrary method, perhaps in DefaultGroovyMethods
but perhaps in some other (binary) library, which takes a (CPS-transformed) closure, the behavior is nonsensical:
[1, 2].whatever {println it}
will call whatever
, and when that method calls Closure.call
, the closure is run correctly…but once it returns, the whole call to whatever
is suddenly terminated (with CpsCallableInvocation
), and so the result is that the closure is only ever called once, and the overall return value is meaningless.
What we would prefer is that if the closure can run synchronously, we run it without CPS transformation and let the whatever
method run to completion synchronously, so that basic calls like
def x = [1, 2].find {it %2 == 0}
will work. But if something inside the closure calls Continuable.suspend
, then we need to notice that the call stack includes non-CPS methods, and we want to throw an error with a helpful message. Thus for example in a Workflow
[1, 2].each = {echo "found ${it}"}
would work (since EchoStep
is synchronous and so tells DSL.invokeMethod
to return null
immediately), but
[1, 2].each = {sh "echo found ${it}"}
would throw an error (since DurableTaskStep
is asynchronous and so tells DSL.invokeMethod
to call Continuable.suspend
).
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.