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

      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.

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

          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 svanoort abayer

          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 svanoort abayer

          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.

           

          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.  

          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.

          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.

          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

           

          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  

          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.

          amirbarkal’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.

          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. amirbarkal ’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.

            Unassigned Unassigned
            erez_arbell Erez Arbell
            Votes:
            1 Vote for this issue
            Watchers:
            7 Start watching this issue

              Created:
              Updated:
              Resolved: