Skip to content

ConcurrentModificationException in MDC after upgrading to 0.59 #1753

@theigl

Description

@theigl

I just upgraded from 0.58 to 0.59 and I frequently see these exceptions now:

  java.util.ConcurrentModificationException: null
        at java.base/java.util.HashMap$HashIterator.nextNode(HashMap.java:1493)
        at java.base/java.util.HashMap$EntryIterator.next(HashMap.java:1526)
        at java.base/java.util.HashMap$EntryIterator.next(HashMap.java:1524)
        at java.base/java.util.HashMap.putMapEntries(HashMap.java:507)
        at java.base/java.util.HashMap.<init>(HashMap.java:485)
        at ch.qos.logback.classic.util.LogbackMDCAdapter.getCopyOfContextMap(LogbackMDCAdapter.java:189)
        at org.slf4j.MDC.getCopyOfContextMap(MDC.java:248)
        at com.myproject.base.util.executor.MDCExecutorService.wrapTask(MDCExecutorService.java:24)
        at com.myproject.base.util.executor.WrappingExecutorService.submit(WrappingExecutorService.java:54)
        at com.myproject.base.util.executor.WrappingExecutorService.submit(WrappingExecutorService.java:54)
        at io.micrometer.core.instrument.internal.TimedExecutorService.submit(TimedExecutorService.java:77)
        at org.springframework.core.task.support.TaskExecutorAdapter.submit(TaskExecutorAdapter.java:127)
        at org.springframework.aop.interceptor.AsyncExecutionAspectSupport.doSubmit(AsyncExecutionAspectSupport.java:290)
        at org.springframework.aop.interceptor.AsyncExecutionInterceptor.invoke(AsyncExecutionInterceptor.java:129)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691)

MDCExecutorService looks like this:

  @Slf4j
  public final class MDCExecutorService extends WrappingExecutorService {

	public MDCExecutorService(ExecutorService delegate) {
		super(delegate);
	}

	@Override
	protected <T> Callable<T> wrapTask(Callable<T> callable) {
		final Map<String, String> context = MDC.getCopyOfContextMap();
		return new MDCCallable<>(callable, context);
	}

	@RequiredArgsConstructor
	private static class MDCCallable<T> implements Callable<T> {

		@NonNull
		private final Callable<T> delegate;
		private final Map<String, String> context;

		@Override
		public T call() throws Exception {
			if (context == null) {
				MDC.clear();
			} else {
				MDC.setContextMap(context);
			}
			try {
				return delegate.call();
			} finally {
				MDC.clear();
			}
		}
	}
  }

Possibly related to #1688.

Metadata

Metadata

Assignees

Labels

type: bugBug report and fix

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions