testcontainers / testcontainers/testcontainers-java

ConcurrentModificationException using new Startable.dependsOn(startable)

Offen
#1,722 4 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

resolution/acknowledged type/bug
Vorherrschende Sprache
Java
Sterne
8.7k
Forks
1.9k
Ø Merge
2 T. 17 Std.
Gemergte PRs (30 T.)
9

Beschreibung

I ran into an error in one of my TravisCI builds using the new dependsOn mechanism:

    13780 ERROR 🐳 [postgres:9.6.12]  - Could not start container
    java.util.ConcurrentModificationException
    	at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1660)
    	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
    	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
    	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:550)
    	at java.base/java.util.stream.AbstractPipeline.evaluateToArrayNode(AbstractPipeline.java:260)
    	at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:517)
    	at org.testcontainers.containers.GenericContainer.applyConfiguration(GenericContainer.java:510)
    	at org.testcontainers.containers.GenericContainer.tryStart(GenericContainer.java:301)
    	at org.testcontainers.containers.GenericContainer.lambda$doStart$0(GenericContainer.java:285)
    	at org.rnorth.ducttape.unreliables.Unreliables.retryUntilSuccess(Unreliables.java:81)
    	at org.testcontainers.containers.GenericContainer.doStart(GenericContainer.java:283)
    	at org.testcontainers.containers.GenericContainer.start(GenericContainer.java:272)
    	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
    	at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1654)
    	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
    	at java.base/java.util.stream.ForEachOps$ForEachTask.compute(ForEachOps.java:290)
    	at java.base/java.util.concurrent.CountedCompleter.exec(CountedCompleter.java:746)
    	at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290)
    	at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1020)
    	at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1656)
    	at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1594)
    	at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:177)

My containers are defined like this:

	@Container
	public static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>()
					.withNetworkAliases("testpostgres")
					.withDatabaseName("testdb");
	
    @Container
    public static MicroProfileApplication<?> app = new MicroProfileApplication<>()
                    .withEnv("POSTGRES_HOSTNAME", "testpostgres")
                    .withEnv("POSTGRES_PORT", "5432")
                    .withAppContextRoot("/myservice")
                    .dependsOn(postgres);

Using the latest version of testcontainers (1.12.0), the exception lines up with this bit of code:

    private void applyConfiguration(CreateContainerCmd createCommand) {
        HostConfig hostConfig = buildHostConfig();
        createCommand.withHostConfig(hostConfig);

        // Set up exposed ports (where there are no host port bindings defined)
        ExposedPort[] portArray = exposedPorts.stream()
                .map(ExposedPort::new)
                .toArray(ExposedPort[]::new);  // << --- CONCURRENT MOD EX HERE

It should also be noted that I am starting my containers in parallel like this:

containersToStart.parallelStream().forEach(GenericContainer::start);

which should be OK, since I believe the main value of dependsOn is that it allows us to do parallel container start without needing to worry about dependencies.

Beitragsleitfaden

Beitragsleitfaden öffnen

Erste Schritte

  1. Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
  3. Forke das Repository und arbeite in einem Branch.
  4. Öffne einen Pull Request, der die Issue-Nummer nennt.

Rechercherichtung

Beginnen Sie in GenericContainer.applyConfiguration beim exposedPorts-Stream und verfolgen Sie dann die im Bericht gezeigten dependsOn- und parallelen GenericContainer.start-Pfade. Reproduzieren Sie das PostgreSQL/Application-Setup mit containersToStart.parallelStream().forEach(GenericContainer::start), und betrachten Sie das Issue als abgeschlossen, wenn abhängige Container ohne ConcurrentModificationException starten.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
docker, java
Bereich
devops, testing
Issue-Typ
Bug
Schwierigkeit
3/5
Geschätzter Aufwand
1-2 Tage
Aktivitätsstatus
Veraltet
Klarheit
Größtenteils klar
Anfängerfreundlichkeit
35/100

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.