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

Timeout is caught by the most internal try-catch, but should be caught by the try-catch that surrounds the timeout step

    Details

    • Similar Issues:

      Description

      Simple example:

      node('master') {
        try {
          timeout(time: 5, unit: 'SECONDS') {
            try {
              sleep(30)
            }
            catch (err) {
              echo "For some reason, this catch is activated. Error: ${err.getMessage()}"
            }
            echo "This should not be executed, but it is!"
          }
        }
        catch (err) {
          echo "I expect that this catch will be activated. Error: ${err.getMessage()}"
        }
      }
      

      I expect that when a timeout is reached, the exception will be caught by the try-catch that surrounds the "timeout" step.
      But actually, it is caught by the most inner try-catch.
      My goal here is to set timeout to set of actions and if the timeout is reached, I want them all to stop. I also want to have more try-catch inside for handling other issues.
      But the actual behavior is that when the timeout is reached, the most internal catch handles it instead of the try-catch that surrounds the timeout step.

      This issue is similar to JENKINS-39266. I do not understand why it was closed.

      By the way, the 

      err.getMessage()

      prints "null", which is also a problem.

        Attachments

          Issue Links

            Activity

            Hide
            oleg_nenashev Oleg Nenashev added a comment -

            Fortunately or not, this is as-designed behavior. try/catch is a part of generic Groovy DSL. If you do not expecify explicit type of exception to be caught, it will catch everything including Jenkins Pipeline exceptions (e.g. blacklisted methods from script security). Once you start doing try/catch in Pipeline, you take full responsibility for exception handling.

            CC Sam Van Oort Andrew Bayer

            Show
            oleg_nenashev Oleg Nenashev added a comment - Fortunately or not, this is as-designed behavior. try/catch is a part of generic Groovy DSL. If you do not expecify explicit type of exception to be caught, it will catch everything including Jenkins Pipeline exceptions (e.g. blacklisted methods from script security). Once you start doing try/catch in Pipeline, you take full responsibility for exception handling. CC Sam Van Oort Andrew Bayer
            Hide
            erez_arbell Erez Arbell added a comment -

            Thank you Oleg Nenashev for the response.

            This behavior still seams un-intuitive and not useful.

            As I wrote above, If I surround a block with timeout, I want to stop the whole block once the timeout reaches, regardless of try-catch inside the block.

            What are the pros of having the current behavior? Is there a use case for it?

            This is a special problem because of the current known limitation of pipeline of distinguishing between timeout and abort when happen during 'sh'. See, for example JENKINS-28822JENKINS-34376, and more.

             

            Show
            erez_arbell Erez Arbell added a comment - Thank you Oleg Nenashev for the response. This behavior still seams un-intuitive and not useful. As I wrote above, If I surround a block with timeout, I want to stop the whole block once the timeout reaches, regardless of try-catch inside the block. What are the pros of having the current behavior? Is there a use case for it? This is a special problem because of the current known limitation of pipeline of distinguishing between timeout and abort when happen during 'sh'. See, for example  JENKINS-28822 ,  JENKINS-34376 , and more.  
            Hide
            dnusbaum Devin Nusbaum added a comment -

            This looks like the same class of problem as JENKINS-34973. It's unclear to me if we could do something out-of-band as Jesse suggests in that issue to change the behavior here.

            Show
            dnusbaum Devin Nusbaum added a comment - This looks like the same class of problem as JENKINS-34973 . It's unclear to me if we could do something out-of-band as Jesse suggests in that issue to change the behavior here.
            Hide
            amirbarkal Amir Barkal added a comment -

            Another simple reproduction of the timeout() step not throwing an exception:

            node() {
              try {
               timeout(time: 3 as Integer, unit: 'SECONDS') {
                 int result = sh(returnStatus: true, script:'sleep 5')
               }
              }
              catch(e) {
                println "TIMEOUT" // Will never get here
                throw e
              }
            }
            

             

             

            Env details:

            Jenkins 2.138

            workflow-basic-steps 2.9

             

            Show
            amirbarkal Amir Barkal added a comment - Another simple reproduction of the timeout() step not throwing an exception: node() { try { timeout(time: 3 as Integer , unit: 'SECONDS' ) { int result = sh(returnStatus: true , script: 'sleep 5' ) } } catch (e) { println "TIMEOUT" // Will never get here throw e } }     Env details: Jenkins  2.138 workflow-basic-steps 2.9  
            Hide
            jglick Jesse Glick added a comment -

            Erez Arbell’s example is just as designed. timeout sends an interrupt to the innermost running step. How that step processes the interruption will depend on its implementation. In most cases it will respond by failing with that FlowInterruptedException. If you catch that exception and decline to rethrow it, so be it.

            Amir Barkal’s example is a little different. returnStatus was returning the SIGTERM, typically 143. This behavior was changed in JENKINS-28822, a few weeks after that comment.

            I do not believe JENKINS-34973 is related.

            Show
            jglick Jesse Glick added a comment - Erez Arbell ’s example is just as designed. timeout sends an interrupt to the innermost running step. How that step processes the interruption will depend on its implementation. In most cases it will respond by failing with that FlowInterruptedException . If you catch that exception and decline to rethrow it, so be it. Amir Barkal ’s example is a little different. returnStatus was returning the SIGTERM , typically 143. This behavior was changed in JENKINS-28822 , a few weeks after that comment. I do not believe JENKINS-34973 is related.

              People

              • Assignee:
                Unassigned
                Reporter:
                erez_arbell Erez Arbell
              • Votes:
                1 Vote for this issue
                Watchers:
                6 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: