Skip to content

Concurrent modification exception in Timetable #5933

@vpaturet

Description

@vpaturet

We see occasionally in our production environment a concurrent access issue on a Timetable object.
It seems that a reader thread (GraphQL API call) iterates over the TripTimes collection of a Timetable object while this collection is being modified concurrently by another thread.
In theory this should not happen since the TimetableSnapshot should ensure that all write operations on Timetable objects happen before the Timetables are handed over to reader threads.

Exception while fetching data (/stopPlaces[0]/estimatedCalls) : null
java.util.ConcurrentModificationException: null
	at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1095)
	at java.base/java.util.ArrayList$Itr.next(ArrayList.java:1049)
	at org.opentripplanner.routing.stoptimes.StopTimesHelper.listTripTimeShortsForPatternAtStop(StopTimesHelper.java:247)
	at org.opentripplanner.routing.stoptimes.StopTimesHelper.stopTimesForStop(StopTimesHelper.java:65)
	at org.opentripplanner.transit.service.DefaultTransitService.stopTimesForStop(DefaultTransitService.java:325)
	at org.opentripplanner.apis.transmodel.model.stop.StopPlaceType.getTripTimesForStop(StopPlaceType.java:438)
	at org.opentripplanner.apis.transmodel.model.stop.StopPlaceType.lambda$create$16(StopPlaceType.java:378)
	at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:273)
	at java.base/java.util.HashMap$KeySpliterator.tryAdvance(HashMap.java:1736)
	at java.base/java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:129)
	at java.base/java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:527)
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:513)
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
	at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
	at org.opentripplanner.apis.transmodel.model.stop.StopPlaceType.lambda$create$17(StopPlaceType.java:400)
	at graphql.execution.ExecutionStrategy.invokeDataFetcher(ExecutionStrategy.java:329)
	at graphql.execution.ExecutionStrategy.fetchField(ExecutionStrategy.java:305)
s	at graphql.execution.ExecutionStrategy.fetchField(ExecutionStrategy.java:243)
	at graphql.execution.ExecutionStrategy.resolveFieldWithInfo(ExecutionStrategy.java:214)
	at graphql.execution.AsyncExecutionStrategy.execute(AsyncExecutionStrategy.java:63)
	at graphql.execution.ExecutionStrategy.completeValueForObject(ExecutionStrategy.java:729)
	at graphql.execution.ExecutionStrategy.completeValue(ExecutionStrategy.java:502)
	at graphql.execution.ExecutionStrategy.completeValueForList(ExecutionStrategy.java:613)
	at graphql.execution.ExecutionStrategy.completeValueForList(ExecutionStrategy.java:561)
	at graphql.execution.ExecutionStrategy.completeValue(ExecutionStrategy.java:487)
	at graphql.execution.ExecutionStrategy.completeField(ExecutionStrategy.java:453)
	at graphql.execution.ExecutionStrategy.lambda$resolveFieldWithInfo$1(ExecutionStrategy.java:216)
	at java.base/java.util.concurrent.CompletableFuture.uniApplyNow(CompletableFuture.java:684)
	at java.base/java.util.concurrent.CompletableFuture.uniApplyStage(CompletableFuture.java:662)
	at java.base/java.util.concurrent.CompletableFuture.thenApply(CompletableFuture.java:2200)
	at graphql.execution.ExecutionStrategy.resolveFieldWithInfo(ExecutionStrategy.java:215)
	at graphql.execution.AsyncExecutionStrategy.execute(AsyncExecutionStrategy.java:63)
	at graphql.execution.Execution.executeOperation(Execution.java:162)
	at graphql.execution.Execution.execute(Execution.java:104)
	at graphql.GraphQL.execute(GraphQL.java:568)
	at graphql.GraphQL.lambda$parseValidateAndExecute$13(GraphQL.java:487)
	at java.base/java.util.concurrent.CompletableFuture.uniComposeStage(CompletableFuture.java:1187)
	at java.base/java.util.concurrent.CompletableFuture.thenCompose(CompletableFuture.java:2341)
	at graphql.GraphQL.parseValidateAndExecute(GraphQL.java:482)
	at graphql.GraphQL.lambda$executeAsync$9(GraphQL.java:440)
	at java.base/java.util.concurrent.CompletableFuture.uniComposeStage(CompletableFuture.java:1187)
	at java.base/java.util.concurrent.CompletableFuture.thenCompose(CompletableFuture.java:2341)
	at graphql.GraphQL.executeAsync(GraphQL.java:428)
	at graphql.GraphQL.execute(GraphQL.java:366)
	at org.opentripplanner.apis.transmodel.TransmodelGraph.executeGraphQL(TransmodelGraph.java:66)
	at org.opentripplanner.apis.transmodel.TransmodelAPI.getGraphQL(TransmodelAPI.java:113)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory.lambda$static$0(ResourceMethodInvocationHandlerFactory.java:52)
	at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$1.run(AbstractJavaResourceMethodDispatcher.java:146)
	at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:189)
	at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$ResponseOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:176)
	at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:93)
	at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:478)
	at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:400)
	at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:81)
	at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:274)
	at org.glassfish.jersey.internal.Errors$1.call(Errors.java:248)
	at org.glassfish.jersey.internal.Errors$1.call(Errors.java:244)
	at org.glassfish.jersey.internal.Errors.process(Errors.java:292)
	at org.glassfish.jersey.internal.Errors.process(Errors.java:274)
	at org.glassfish.jersey.internal.Errors.process(Errors.java:244)
	at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:266)
	at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:253)
	at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:696)
	at org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpContainer.service(GrizzlyHttpContainer.java:367)
	at org.glassfish.grizzly.http.server.HttpHandler$1.run(HttpHandler.java:190)
	at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:535)
	at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:515)
	at java.base/java.lang.Thread.run(Thread.java:1583)

Metadata

Metadata

Assignees

No one assigned

    Labels

    !BugApply to issues describing a bug and PRs witch fixes it.+Real-TimeThe issue/PR is related to RealTime updates

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions