Uploaded image for project: 'Jenkins'
  1. Jenkins
  2. JENKINS-31484

Endless loop in DefaultInvoker.getProperty when accessing field via getter/setter without @

    XMLWordPrintable

    Details

    • Similar Issues:

      Description

      The following script for some reason will make Jenkins go out of memory and will never complete the execution.

      node {
      	HipNotifier chip = new HipNotifier('A')
          echo chip.name	
      }
      
      public class HipNotifier {
          private String name;
      
          public HipNotifier(String pName) {
              this.name = pName
          }
      
          String getName() {
              return name
          }
      }
      

        Attachments

          Issue Links

            Activity

            vexdev Luca Vitucci created issue -
            vexdev Luca Vitucci made changes -
            Field Original Value New Value
            Description The following script for some reason will make Jenkins go out of memory and will never complete the execution.


            {code:java}
            node {
            HipNotifier chip = new HipNotifier('A', 'B', ["C","D"])
                echo chip.name
            }

            public class HipNotifier {
                private String name;
                private String imageUrl;
                private List<String> quotes;

                public HipNotifier(String pName, String imageUrl, List<String> pQuotes) {
                    this.name = pName
                    this.quotes = pQuotes
                    this.imageUrl = imageUrl
                }

                String getName() {
                    return name
                }

                public String getUrl() {
                    return imageUrl;
                }

                public String getRandomQuote() {
                    return quotes.get(new Random().nextInt(quotes.size()))
                }
            }
            {code}
            The following script for some reason will make Jenkins go out of memory and will never complete the execution.


            {code:java}
            node {
            HipNotifier chip = new HipNotifier('A', 'B', ["C", "D"])
                echo chip.name
            }

            public class HipNotifier {
                private String name;
                private String imageUrl;
                private List<String> quotes;

                public HipNotifier(String pName, String imageUrl, List<String> pQuotes) {
                    this.name = pName
                    this.quotes = pQuotes
                    this.imageUrl = imageUrl
                }

                String getName() {
                    return name
                }
            }
            {code}
            vexdev Luca Vitucci made changes -
            Description The following script for some reason will make Jenkins go out of memory and will never complete the execution.


            {code:java}
            node {
            HipNotifier chip = new HipNotifier('A', 'B', ["C", "D"])
                echo chip.name
            }

            public class HipNotifier {
                private String name;
                private String imageUrl;
                private List<String> quotes;

                public HipNotifier(String pName, String imageUrl, List<String> pQuotes) {
                    this.name = pName
                    this.quotes = pQuotes
                    this.imageUrl = imageUrl
                }

                String getName() {
                    return name
                }
            }
            {code}
            The following script for some reason will make Jenkins go out of memory and will never complete the execution.


            {code:java}
            node {
            HipNotifier chip = new HipNotifier('A')
                echo chip.name
            }

            public class HipNotifier {
                private String name;

                public HipNotifier(String pName) {
                    this.name = pName
                }

                String getName() {
                    return name
                }
            }
            {code}
            Hide
            vexdev Luca Vitucci added a comment - - edited

            I managed to reduce the script up to this, Quite strange, it looks like workflow-plugin does not like new class declarations?

            Show
            vexdev Luca Vitucci added a comment - - edited I managed to reduce the script up to this, Quite strange, it looks like workflow-plugin does not like new class declarations?
            Hide
            vexdev Luca Vitucci added a comment -

            Update:

            I managed to track it to the actual cause, which is the getter.
            See following example:

            node {
                Something some = new Something('Ciao, Mondo!')
                echo some.name
            }
            
            public class Something {
                private String name
            
                public Something(String name) {
                    this.name = name
                }
            }
            

            That is working fine, instead if we add a getter, it stops working, and hangs jenkins:

            node {
                Something some = new Something('Ciao, Mondo!')
                echo some.name
            }
            
            public class Something {
                private String name
            
                public Something(String name) {
                    this.name = name
                }
            
                String getName() {return name}
            }
            
            Show
            vexdev Luca Vitucci added a comment - Update: I managed to track it to the actual cause, which is the getter. See following example: node { Something some = new Something( 'Ciao, Mondo!' ) echo some.name } public class Something { private String name public Something( String name) { this .name = name } } That is working fine, instead if we add a getter, it stops working, and hangs jenkins: node { Something some = new Something( 'Ciao, Mondo!' ) echo some.name } public class Something { private String name public Something( String name) { this .name = name } String getName() { return name} }
            Hide
            jglick Jesse Glick added a comment -

            Reproducible:

            "Computer.threadPoolForRemoting [#4]" … runnable …
               java.lang.Thread.State: RUNNABLE
            	at java.lang.Throwable.fillInStackTrace(Native Method)
            	at java.lang.Throwable.fillInStackTrace(Throwable.java:783)
            	- locked <0x00000007ae52b740> (a org.codehaus.groovy.runtime.InvokerInvocationException)
            	at java.lang.Throwable.<init>(Throwable.java:250)
            	at java.lang.Exception.<init>(Exception.java:54)
            	at java.lang.RuntimeException.<init>(RuntimeException.java:51)
            	at groovy.lang.GroovyRuntimeException.<init>(GroovyRuntimeException.java:49)
            	at org.codehaus.groovy.runtime.InvokerInvocationException.<init>(InvokerInvocationException.java:31)
            	at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:97)
            	at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
            	at groovy.lang.MetaClassImpl.getProperty(MetaClassImpl.java:1612)
            	at groovy.lang.MetaClassImpl.getProperty(MetaClassImpl.java:3343)
            	at Something.getProperty(WorkflowScript)
            	at org.codehaus.groovy.runtime.InvokerHelper.getProperty(InvokerHelper.java:156)
            	at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.getProperty(ScriptBytecodeAdapter.java:452)
            	at com.cloudbees.groovy.cps.sandbox.DefaultInvoker.getProperty(DefaultInvoker.java:25)
            	at com.cloudbees.groovy.cps.impl.PropertyAccessBlock.rawGet(PropertyAccessBlock.java:17)
            	at com.cloudbees.groovy.cps.impl.PropertyishBlock$ContinuationImpl.get(PropertyishBlock.java:62)
            	at com.cloudbees.groovy.cps.LValueBlock$GetAdapter.receive(LValueBlock.java:30)
            	at com.cloudbees.groovy.cps.impl.PropertyishBlock$ContinuationImpl.fixName(PropertyishBlock.java:54)
            	at sun.reflect.GeneratedMethodAccessor84.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.Continuable.run0(Continuable.java:145)
            	at org.jenkinsci.plugins.workflow.cps.CpsThread.runNextChunk(CpsThread.java:164)
            	at …
            
            Show
            jglick Jesse Glick added a comment - Reproducible: "Computer.threadPoolForRemoting [#4]" … runnable … java.lang.Thread.State: RUNNABLE at java.lang.Throwable.fillInStackTrace(Native Method) at java.lang.Throwable.fillInStackTrace(Throwable.java:783) - locked <0x00000007ae52b740> (a org.codehaus.groovy.runtime.InvokerInvocationException) at java.lang.Throwable.<init>(Throwable.java:250) at java.lang.Exception.<init>(Exception.java:54) at java.lang.RuntimeException.<init>(RuntimeException.java:51) at groovy.lang.GroovyRuntimeException.<init>(GroovyRuntimeException.java:49) at org.codehaus.groovy.runtime.InvokerInvocationException.<init>(InvokerInvocationException.java:31) at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:97) at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233) at groovy.lang.MetaClassImpl.getProperty(MetaClassImpl.java:1612) at groovy.lang.MetaClassImpl.getProperty(MetaClassImpl.java:3343) at Something.getProperty(WorkflowScript) at org.codehaus.groovy.runtime.InvokerHelper.getProperty(InvokerHelper.java:156) at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.getProperty(ScriptBytecodeAdapter.java:452) at com.cloudbees.groovy.cps.sandbox.DefaultInvoker.getProperty(DefaultInvoker.java:25) at com.cloudbees.groovy.cps.impl.PropertyAccessBlock.rawGet(PropertyAccessBlock.java:17) at com.cloudbees.groovy.cps.impl.PropertyishBlock$ContinuationImpl.get(PropertyishBlock.java:62) at com.cloudbees.groovy.cps.LValueBlock$GetAdapter.receive(LValueBlock.java:30) at com.cloudbees.groovy.cps.impl.PropertyishBlock$ContinuationImpl.fixName(PropertyishBlock.java:54) at sun.reflect.GeneratedMethodAccessor84.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.Continuable.run0(Continuable.java:145) at org.jenkinsci.plugins.workflow.cps.CpsThread.runNextChunk(CpsThread.java:164) at …
            jglick Jesse Glick made changes -
            Labels hang outofmemoryerror hang outofmemoryerror robustness
            jglick Jesse Glick made changes -
            Summary Build is going OutOfMemory Flow goes into endless loop in DefaultInvoker.getProperty when accessing field via getter
            jglick Jesse Glick made changes -
            Link This issue depends on JENKINS-25550 [ JENKINS-25550 ]
            Hide
            jglick Jesse Glick added a comment -

            A hard kill from JENKINS-25550 allows the build to be marked as aborted, but does not actually kill the CpsVmExecutorService call, so Jenkins will still crash. Probably need to escalate to a Thread.stop in such a case.

            Show
            jglick Jesse Glick added a comment - A hard kill from JENKINS-25550 allows the build to be marked as aborted, but does not actually kill the CpsVmExecutorService call, so Jenkins will still crash. Probably need to escalate to a Thread.stop in such a case.
            rtyler R. Tyler Croy made changes -
            Workflow JNJira [ 166884 ] JNJira + In-Review [ 182502 ]
            abayer Andrew Bayer made changes -
            Component/s pipeline-general [ 21692 ]
            abayer Andrew Bayer made changes -
            Component/s workflow-plugin [ 18820 ]
            jglick Jesse Glick made changes -
            Link This issue is related to JENKINS-32986 [ JENKINS-32986 ]
            jglick Jesse Glick made changes -
            Component/s workflow-cps-plugin [ 21713 ]
            Component/s pipeline [ 21692 ]
            danielbeck Daniel Beck made changes -
            Epic Link JENKINS-35390 [ 171183 ]
            Hide
            junpengl Junpeng Luo added a comment -

            Similar issue occured when using getter in class of pipeline global shared lib. We decided not use getters for now. Any solutions for this problem?

            Show
            junpengl Junpeng Luo added a comment - Similar issue occured when using getter in class of pipeline global shared lib. We decided not use getters for now. Any solutions for this problem?
            Hide
            jglick Jesse Glick added a comment -

            As a workaround, try explicitly calling .getName() rather than using the .name shorthand. Have not yet found time to track down the actual issue; probably some mistake in groovy-cps.

            Show
            jglick Jesse Glick added a comment - As a workaround, try explicitly calling .getName() rather than using the .name shorthand. Have not yet found time to track down the actual issue; probably some mistake in groovy-cps .
            Hide
            jglick Jesse Glick added a comment -

            Possibly related to JENKINS-38021?

            Show
            jglick Jesse Glick added a comment - Possibly related to JENKINS-38021 ?
            jglick Jesse Glick made changes -
            Link This issue relates to JENKINS-38021 [ JENKINS-38021 ]
            jglick Jesse Glick made changes -
            Status Open [ 1 ] In Progress [ 3 ]
            Hide
            jglick Jesse Glick added a comment -

            Reproduced hang in test, but cannot find anything in the physical thread dump; high CPU activity seems to be in GC threads. I do see:

            com.cloudbees.jenkins.support.SupportPlugin writeBundle
            WARNING: Could not attach 'nodes/master/pipeline-thread-dump.txt' to support bundle
            java.lang.StackOverflowError
            	at com.cloudbees.groovy.cps.impl.SourceLocation.toStackTrace(SourceLocation.java:22)
            	at com.cloudbees.groovy.cps.impl.CallEnv.buildStackTraceElements(CallEnv.java:101)
            	at com.cloudbees.groovy.cps.impl.FunctionCallEnv.buildStackTraceElements(FunctionCallEnv.java:13)
            	at com.cloudbees.groovy.cps.impl.ProxyEnv.buildStackTraceElements(ProxyEnv.java:64)
            	at com.cloudbees.groovy.cps.impl.ProxyEnv.buildStackTraceElements(ProxyEnv.java:64)
            	at com.cloudbees.groovy.cps.impl.CallEnv.buildStackTraceElements(CallEnv.java:103)
            	at com.cloudbees.groovy.cps.impl.FunctionCallEnv.buildStackTraceElements(FunctionCallEnv.java:13)
            	at …
            
            Show
            jglick Jesse Glick added a comment - Reproduced hang in test, but cannot find anything in the physical thread dump; high CPU activity seems to be in GC threads. I do see: com.cloudbees.jenkins.support.SupportPlugin writeBundle WARNING: Could not attach 'nodes/master/pipeline-thread-dump.txt' to support bundle java.lang.StackOverflowError at com.cloudbees.groovy.cps.impl.SourceLocation.toStackTrace(SourceLocation.java:22) at com.cloudbees.groovy.cps.impl.CallEnv.buildStackTraceElements(CallEnv.java:101) at com.cloudbees.groovy.cps.impl.FunctionCallEnv.buildStackTraceElements(FunctionCallEnv.java:13) at com.cloudbees.groovy.cps.impl.ProxyEnv.buildStackTraceElements(ProxyEnv.java:64) at com.cloudbees.groovy.cps.impl.ProxyEnv.buildStackTraceElements(ProxyEnv.java:64) at com.cloudbees.groovy.cps.impl.CallEnv.buildStackTraceElements(CallEnv.java:103) at com.cloudbees.groovy.cps.impl.FunctionCallEnv.buildStackTraceElements(FunctionCallEnv.java:13) at …
            jglick Jesse Glick made changes -
            Remote Link This issue links to "groovy-cps PR 45 (Web Link)" [ 15344 ]
            jglick Jesse Glick made changes -
            Status In Progress [ 3 ] In Review [ 10005 ]
            jglick Jesse Glick made changes -
            Status In Review [ 10005 ] In Progress [ 3 ]
            jglick Jesse Glick made changes -
            Status In Progress [ 3 ] In Review [ 10005 ]
            jglick Jesse Glick made changes -
            Link This issue relates to JENKINS-38021 [ JENKINS-38021 ]
            jglick Jesse Glick made changes -
            Link This issue is duplicated by JENKINS-38021 [ JENKINS-38021 ]
            Hide
            jglick Jesse Glick added a comment -

            Using .getName() rather than .name is not the issue, since the bug is inside the getter itself. The workaround is to use the more explicit:

            String getName() {this.@name}
            

            Similarly for setters:

            void setName(String name) {this.@name = name}
            
            Show
            jglick Jesse Glick added a comment - Using .getName() rather than .name is not the issue, since the bug is inside the getter itself. The workaround is to use the more explicit: String getName() { this .@name} Similarly for setters: void setName( String name) { this .@name = name}
            jglick Jesse Glick made changes -
            Summary Flow goes into endless loop in DefaultInvoker.getProperty when accessing field via getter Endless loop in DefaultInvoker.getProperty when accessing field via getter/setter without @
            Hide
            jglick Jesse Glick added a comment -

            It is worth noting that this behavior of accessing the backing field directly is done in order to prevent a stack overflow when using the property access syntax within a class that defines the property.

            Intuitive enough, though it is hard to see how a CompilationCustomizer is supposed to be informed of this difference. In the proposed PR I just used trial and error. Javadoc is minimal to nonexistent, as is typical in Groovy sources.

            Show
            jglick Jesse Glick added a comment - It is worth noting that this behavior of accessing the backing field directly is done in order to prevent a stack overflow when using the property access syntax within a class that defines the property. Intuitive enough, though it is hard to see how a CompilationCustomizer is supposed to be informed of this difference. In the proposed PR I just used trial and error. Javadoc is minimal to nonexistent, as is typical in Groovy sources.
            jglick Jesse Glick made changes -
            Remote Link This issue links to "Groovy docs: Properties (Web Link)" [ 15347 ]
            jglick Jesse Glick made changes -
            Status In Review [ 10005 ] In Progress [ 3 ]
            jglick Jesse Glick made changes -
            Status In Progress [ 3 ] In Review [ 10005 ]
            jglick Jesse Glick made changes -
            Resolution Fixed [ 1 ]
            Status In Review [ 10005 ] Resolved [ 5 ]
            jglick Jesse Glick made changes -
            Link This issue is duplicated by JENKINS-41412 [ JENKINS-41412 ]
            jglick Jesse Glick made changes -
            Link This issue relates to JENKINS-41984 [ JENKINS-41984 ]
            jglick Jesse Glick made changes -
            Link This issue is duplicated by JENKINS-42170 [ JENKINS-42170 ]
            leedega Kevin Phillips made changes -
            Link This issue relates to JENKINS-45834 [ JENKINS-45834 ]
            Hide
            dnusbaum Devin Nusbaum added a comment -

            Ran into another variant of this issue, and opened a PR against groovy-cps with an ignored test case: https://github.com/cloudbees/groovy-cps/pull/95. The issue is that a getter like the following works in regular Groovy, but fails with a StackOverflowError in groovy-cps:

            String getName() {this.name}
            
            Show
            dnusbaum Devin Nusbaum added a comment - Ran into another variant of this issue, and opened a PR against groovy-cps with an ignored test case: https://github.com/cloudbees/groovy-cps/pull/95 . The issue is that a getter like the following works in regular Groovy, but fails with a StackOverflowError in groovy-cps: String getName() { this .name}
            dnusbaum Devin Nusbaum made changes -
            Remote Link This issue links to "cloudbees/groovy-cps#95 (Web Link)" [ 22418 ]
            Hide
            megaloni Megan Smith added a comment -

            This still seems broken - we just ran into it with Jenkins version Jenkins 2.235.2

            Show
            megaloni Megan Smith added a comment - This still seems broken - we just ran into it with Jenkins version Jenkins 2.235.2

              People

              Assignee:
              jglick Jesse Glick
              Reporter:
              vexdev Luca Vitucci
              Votes:
              4 Vote for this issue
              Watchers:
              13 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved: