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

Concurrent modification exception on serializing MilestoneStep$DescriptorImpl#milestonesByOrdinalByJob

      On a pipeline script from a multibranch project, after a milestone step invocation, the run log shows:

      Trying to pass milestone 0
      and the stack trace at this gist

      PS: It has been impossible do reproduce the issue.
      PS2: Might be related to two repositories having the same name, replacing hypen-minus characters with underscores (eg: my-repo and my_repo)?.

          [JENKINS-45565] Concurrent modification exception on serializing MilestoneStep$DescriptorImpl#milestonesByOrdinalByJob

          hudson.model.Descriptor#save is synchronized so I can not imagine how a concurrent modification could happen.
          Difficult to work on a fix if it is not reproducible.

          Antonio Muñiz added a comment - hudson.model.Descriptor#save is synchronized so I can not imagine how a concurrent modification could happen. Difficult to work on a fix if it is not reproducible.

          I can confirm this behaviour. Sporadically I got the same error message when starting 4 freshly via jobDsl() generated jobs. Tried to reproduce this with a small example without any luck, sorry. I am using Jenkins 2.60.3 together with Pipeline Milestone Step 1.3.1.

          I assume this has something to do with writing the milestone descriptor to the XML file? Nevertheless all 4 jobs and its milestones are written to it just fine. Workaround for me:

           

          try {
             milestone(ordinal: 1, label: 'ms_init')
          } catch (e) {
             log "milestone ms_init: caught exception: ${e}"
          }
          

          Karsten Günther added a comment - I can confirm this behaviour. Sporadically I got the same error message when starting 4 freshly via jobDsl() generated jobs. Tried to reproduce this with a small example without any luck, sorry. I am using Jenkins 2.60.3 together with Pipeline Milestone Step 1.3.1. I assume this has something to do with writing the milestone descriptor to the XML file? Nevertheless all 4 jobs and its milestones are written to it just fine. Workaround for me:   try { milestone(ordinal: 1, label: 'ms_init' ) } catch (e) { log "milestone ms_init: caught exception: ${e}" }

          Daniel Weber added a comment -

          I just had a quick look at the code. Descriptor#save is synchronized, yes. But MilestoneStep.DescriptorImpl has a map (

          milestonesByOrdinalByJob) which is used in many places. Now if some piece of code modifies that map while Jenkins serialization is iterating over it in order to save it, concurrent modification exceptions can happen. This would fit the stack traces we've seen (Exceptions happen while iterating over a TreeMap, and this is the only one on the Descriptor).

          Maybe it would help to use a ConcurrentSkipListMap instead of a simple TreeMap?

          Daniel Weber added a comment - I just had a quick look at the code. Descriptor#save is synchronized, yes. But MilestoneStep.DescriptorImpl has a map ( milestonesByOrdinalByJob) which is used in many places. Now if some piece of code modifies that map while Jenkins serialization is iterating over it in order to save it, concurrent modification exceptions can happen. This would fit the stack traces we've seen (Exceptions happen while iterating over a TreeMap, and this is the only one on the Descriptor). Maybe it would help to use a ConcurrentSkipListMap instead of a simple TreeMap?

          IMHO it might be worth trying. I have seen another occurence of this exception.

          Javier Delgado added a comment - IMHO it might be worth trying. I have seen another occurence of this exception.

          Brian Saville added a comment -

          We ran into this same problem today. In our case, we have the same job name in different folders (job_1 and subfolder/job_1), so that might be related to the PS2 above.

          Brian Saville added a comment - We ran into this same problem today. In our case, we have the same job name in different folders (job_1 and subfolder/job_1), so that might be related to the PS2 above.

            amuniz Antonio Muñiz
            witokondoria Javier Delgado
            Votes:
            3 Vote for this issue
            Watchers:
            6 Start watching this issue

              Created:
              Updated: