简体   繁体   中英

Jenkins scripted pipleline @NonCPS and StackOverflowError

I have the simple pipeline script:

#!groovy

@org.jenkinsci.plugins.workflow.libs.Library('Some@lib')

import com.cloudbees.groovy.cps.NonCPS

node() {

    echo CheekyEnum.getByName('name1').getName()

}

enum CheekyEnum {

    ENUM_1('name1', 'f1'),
    ENUM_2('name2', 'f2')

    String name
    String field

    CheekyEnum(String name, String field) {
        this.name = name
        this.field = field
    }

    static CheekyEnum getByName(String name) {
        return values().find { it.name == name }
    }
    
    String getName() {
        return name
    }
}

When I run it everything works OK, but if there is a little change in method getName()

@NonCPS
String getName() {
    return name
}

I get a pretty long error stacktrace:

java.lang.StackOverflowError
    at java.lang.ClassLoader.loadClass(ClassLoader.java:398)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
    at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxResolvingClassLoader.lambda$loadClass$0(SandboxResolvingClassLoader.java:51)
    at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxResolvingClassLoader.lambda$load$2(SandboxResolvingClassLoader.java:85)
    at com.github.benmanes.caffeine.cache.BoundedLocalCache.lambda$doComputeIfAbsent$14(BoundedLocalCache.java:2337)
    at java.util.concurrent.ConcurrentHashMap.compute(ConcurrentHashMap.java:1892)
    at com.github.benmanes.caffeine.cache.BoundedLocalCache.doComputeIfAbsent(BoundedLocalCache.java:2335)
    at com.github.benmanes.caffeine.cache.BoundedLocalCache.computeIfAbsent(BoundedLocalCache.java:2318)
    at com.github.benmanes.caffeine.cache.LocalCache.computeIfAbsent(LocalCache.java:111)
    at com.github.benmanes.caffeine.cache.LocalManualCache.get(LocalManualCache.java:54)
    at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxResolvingClassLoader.load(SandboxResolvingClassLoader.java:79)
    ...

Why? Doesn't @NonCPS just make method excluded from CPS transformation?

enum is per se a serializable type. So you should better create a wrapper function for it:

import com.cloudbees.groovy.cps.NonCPS

node() {

    echo getName(CheekyEnum.getByName('name1'))

}
...
@NonCPS
String getName(CheekyEnum cheeky) {
    return cheeky.name
}

The related StackOverflowError could be a bug/smell in the workflow-cps-plugin . Please take a look at its Technical design

Pipeline scripts may mark designated methods with the annotation @NonCPS. These are then compiled normally (except for sandbox security checks).

AFAICS you're running inside a Groovy sandbox. The SandboxInterceptor is probably generating this stack overflow. Running outside the sandbox should fix your issue as well.

BTW you can also readPipeline CPS Method Mismatches for a better understanding of what can be called in non-CPS transformed code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM