Skip to content

ConcurrentModificationException when running tests in parallel #4

@hbf

Description

@hbf

Hi there,

I have just encountered a little bug that manifests itself when you use rocoto's bindSystemProperties() in unit tests and run these concurrently in the same VM. The method internally creates a new iterator from System.getProperties() and the latter may be changed externally, thus resulting in:

INFO: An exception was caught and reported. Message: java.util.ConcurrentModificationException
java.util.ConcurrentModificationException
    at java.util.Hashtable$Enumerator.next(Hashtable.java:1031)
    at org.nnsoft.guice.rocoto.configuration.PropertiesIterator.next(PropertiesIterator.java:93)
    at org.nnsoft.guice.rocoto.configuration.PropertiesIterator.next(PropertiesIterator.java:27)
    at org.nnsoft.guice.rocoto.configuration.ConfigurationModule.bindProperties(ConfigurationModule.java:151)
    at org.nnsoft.guice.rocoto.configuration.ConfigurationModule.bindProperties(ConfigurationModule.java:127)
    at org.nnsoft.guice.rocoto.configuration.ConfigurationModule.bindSystemProperties(ConfigurationModule.java:161)
    ...
    at com.google.inject.AbstractModule.configure(AbstractModule.java:59)
    at com.google.inject.spi.Elements$RecordingBinder.install(Elements.java:223)
    at com.google.inject.AbstractModule.install(AbstractModule.java:118)
        ...
    at com.google.inject.AbstractModule.configure(AbstractModule.java:59)
    at com.google.inject.spi.Elements$RecordingBinder.install(Elements.java:223)
    at com.google.inject.spi.Elements.getElements(Elements.java:101)
    at com.google.inject.internal.InjectorShell$Builder.build(InjectorShell.java:133)
    at com.google.inject.internal.InternalInjectorCreator.build(InternalInjectorCreator.java:103)
    at com.google.inject.Guice.createInjector(Guice.java:95)
    at com.google.inject.Guice.createInjector(Guice.java:72)
    at com.google.inject.Guice.createInjector(Guice.java:62)
    ....
    at org.scalatest.WordSpec$$anonfun$runTests$1.apply(WordSpec.scala:2325)
    at org.scalatest.WordSpec$$anonfun$runTests$1.apply(WordSpec.scala:2325)
    at org.scalatest.SuperEngine$$anonfun$traverseSubNodes$1$1.apply(Engine.scala:323)
    at org.scalatest.SuperEngine$$anonfun$traverseSubNodes$1$1.apply(Engine.scala:311)
    at scala.collection.immutable.List.foreach(List.scala:309)
    at org.scalatest.SuperEngine.traverseSubNodes$1(Engine.scala:311)
    at org.scalatest.SuperEngine.org$scalatest$SuperEngine$$runTestsInBranch(Engine.scala:302)
    at org.scalatest.SuperEngine$$anonfun$traverseSubNodes$1$1.apply(Engine.scala:331)
    at org.scalatest.SuperEngine$$anonfun$traverseSubNodes$1$1.apply(Engine.scala:311)
    at scala.collection.immutable.List.foreach(List.scala:309)
    at org.scalatest.SuperEngine.traverseSubNodes$1(Engine.scala:311)
    at org.scalatest.SuperEngine.org$scalatest$SuperEngine$$runTestsInBranch(Engine.scala:306)
    at org.scalatest.SuperEngine.runTestsImpl(Engine.scala:384)
    at org.scalatest.WordSpec$class.runTests(WordSpec.scala:2325)
    ...
    at org.scalatest.tools.ScalaTestFramework$ScalaTestRunner.run(ScalaTestFramework.scala:217)
    at org.scalatools.testing.Runner2.run(Runner2.java:16)
    at sbt.TestRunner.delegateRun(TestFramework.scala:57)
    at sbt.TestRunner.run(TestFramework.scala:51)
    at sbt.TestRunner.runTest$1(TestFramework.scala:71)
    at sbt.TestRunner.run(TestFramework.scala:80)
    at sbt.TestFramework$$anonfun$6$$anonfun$apply$8$$anonfun$7$$anonfun$apply$9.apply(TestFramework.scala:178)
    at sbt.TestFramework$$anonfun$6$$anonfun$apply$8$$anonfun$7$$anonfun$apply$9.apply(TestFramework.scala:178)
    at sbt.TestFramework$.sbt$TestFramework$$withContextLoader(TestFramework.scala:190)
    at sbt.TestFramework$$anonfun$6$$anonfun$apply$8$$anonfun$7.apply(TestFramework.scala:178)
    at sbt.TestFramework$$anonfun$6$$anonfun$apply$8$$anonfun$7.apply(TestFramework.scala:178)
    at sbt.Tests$$anonfun$makeParallel$1$$anonfun$apply$7.apply(Tests.scala:119)
    at sbt.Tests$$anonfun$makeParallel$1$$anonfun$apply$7.apply(Tests.scala:119)
    at sbt.std.Transform$$anon$3$$anonfun$apply$2.apply(System.scala:47)
    at sbt.std.Transform$$anon$3$$anonfun$apply$2.apply(System.scala:47)
    at sbt.std.Transform$$anon$5.work(System.scala:71)
    at sbt.Execute$$anonfun$submit$1$$anonfun$apply$1.apply(Execute.scala:232)
    at sbt.Execute$$anonfun$submit$1$$anonfun$apply$1.apply(Execute.scala:232)
    at sbt.ErrorHandling$.wideConvert(ErrorHandling.scala:18)
    at sbt.Execute.work(Execute.scala:238)
    at sbt.Execute$$anonfun$submit$1.apply(Execute.scala:232)
    at sbt.Execute$$anonfun$submit$1.apply(Execute.scala:232)
    at sbt.ConcurrentRestrictions$$anon$4$$anonfun$1.apply(ConcurrentRestrictions.scala:159)
    at sbt.CompletionService$$anon$2.call(CompletionService.scala:30)
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
    at java.util.concurrent.FutureTask.run(FutureTask.java:138)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:439)
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
    at java.util.concurrent.FutureTask.run(FutureTask.java:138)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
    at java.lang.Thread.run(Thread.java:680)

Googling for this shows that others have run into the same issue. It's probably sufficient to create a copy before iterating or so.

I am using rococo-6.1.

Thanks,
Kaspar

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions