lhotari opened a new pull request, #23958:
URL: https://github.com/apache/pulsar/pull/23958
Fixes #23952
### Motivation
A deadlock could occur in PendingReadsManager after #23901 changes. This
deadlock was captured in a test case, but based on code analysis this problem
applies to production code execution too.
```
Found one Java-level deadlock:
=============================
"main":
waiting to lock monitor 0x00007fd520fe6f10 (object 0x000010003425f350, a
org.apache.pulsar.broker.service.persistent.PersistentSubscription),
which is held by "PulsarTestContext-executor-OrderedExecutor-0-0"
"PulsarTestContext-executor-OrderedExecutor-0-0":
waiting to lock monitor 0x00007fd4f400dd00 (object 0x000010003425fd70, a
org.apache.pulsar.broker.service.persistent.PersistentDispatcherSingleActiveConsumer),
which is held by "broker-topic-workers-OrderedExecutor-0-0"
"broker-topic-workers-OrderedExecutor-0-0":
waiting to lock monitor 0x00007fd7a406f4a0 (object 0x000010003427f678, a
org.apache.bookkeeper.mledger.impl.cache.PendingReadsManager$PendingRead),
which is held by "PulsarTestContext-executor-OrderedExecutor-0-0"
Java stack information for the threads listed above:
===================================================
"main":
at
org.apache.pulsar.broker.service.persistent.PersistentSubscription.close(PersistentSubscription.java)
- waiting to lock <0x000010003425f350> (a
org.apache.pulsar.broker.service.persistent.PersistentSubscription)
at
org.apache.pulsar.broker.service.persistent.PersistentTopic.lambda$close$56(PersistentTopic.java:1697)
at
org.apache.pulsar.broker.service.persistent.PersistentTopic$$Lambda/0x00007fd54cb397a8.accept(Unknown
Source)
at
java.util.concurrent.ConcurrentHashMap.forEach([email protected]/ConcurrentHashMap.java:1603)
at
org.apache.pulsar.broker.service.persistent.PersistentTopic.lambda$close$57(PersistentTopic.java:1697)
at
org.apache.pulsar.broker.service.persistent.PersistentTopic$$Lambda/0x00007fd54cb39358.accept(Unknown
Source)
at
java.util.concurrent.CompletableFuture.uniAcceptNow([email protected]/CompletableFuture.java:757)
at
java.util.concurrent.CompletableFuture.uniAcceptStage([email protected]/CompletableFuture.java:735)
at
java.util.concurrent.CompletableFuture.thenAccept([email protected]/CompletableFuture.java:2214)
at
org.apache.pulsar.broker.service.persistent.PersistentTopic.close(PersistentTopic.java:1688)
at
org.apache.pulsar.broker.service.BrokerService.lambda$unloadServiceUnit$116(BrokerService.java:2371)
at
org.apache.pulsar.broker.service.BrokerService$$Lambda/0x00007fd54cb76aa8.apply(Unknown
Source)
at
java.util.concurrent.CompletableFuture.uniComposeStage([email protected]/CompletableFuture.java:1187)
at
java.util.concurrent.CompletableFuture.thenCompose([email protected]/CompletableFuture.java:2341)
at
org.apache.pulsar.broker.service.BrokerService.lambda$unloadServiceUnit$118(BrokerService.java:2371)
at
org.apache.pulsar.broker.service.BrokerService$$Lambda/0x00007fd54cb6f800.accept(Unknown
Source)
at
java.util.concurrent.ConcurrentHashMap.forEach([email protected]/ConcurrentHashMap.java:1603)
at
org.apache.pulsar.broker.service.BrokerService.unloadServiceUnit(BrokerService.java:2341)
at
org.apache.pulsar.broker.service.BrokerService.unloadServiceUnit(BrokerService.java:2314)
at
org.apache.pulsar.broker.namespace.OwnedBundle.lambda$handleUnloadRequest$0(OwnedBundle.java:138)
at
org.apache.pulsar.broker.namespace.OwnedBundle$$Lambda/0x00007fd54cb6f5c8.apply(Unknown
Source)
at
java.util.concurrent.CompletableFuture.uniComposeStage([email protected]/CompletableFuture.java:1187)
at
java.util.concurrent.CompletableFuture.thenCompose([email protected]/CompletableFuture.java:2341)
at
org.apache.pulsar.broker.namespace.OwnedBundle.handleUnloadRequest(OwnedBundle.java:138)
at
org.apache.pulsar.broker.namespace.NamespaceService.unloadNamespaceBundle(NamespaceService.java:848)
at
java.lang.invoke.LambdaForm$DMH/0x00007fd54cb71400.invokeVirtual([email protected]/LambdaForm$DMH)
at
java.lang.invoke.LambdaForm$MH/0x00007fd54cb73400.invoke([email protected]/LambdaForm$MH)
at
java.lang.invoke.LambdaForm$MH/0x00007fd54caa0400.invoke([email protected]/LambdaForm$MH)
at
java.lang.invoke.Invokers$Holder.invokeExact_MT([email protected]/Invokers$Holder)
at
java.lang.invoke.MethodHandle.invokeWithArguments([email protected]/MethodHandle.java:733)
at
org.mockito.internal.util.reflection.InstrumentationMemberAccessor$Dispatcher$ByteBuddy$23hKbhcU.invokeWithArguments(Unknown
Source)
at
org.mockito.internal.util.reflection.InstrumentationMemberAccessor.invoke(InstrumentationMemberAccessor.java:251)
at
org.mockito.internal.util.reflection.ModuleMemberAccessor.invoke(ModuleMemberAccessor.java:55)
at
org.mockito.internal.creation.bytebuddy.MockMethodAdvice.tryInvoke(MockMethodAdvice.java:314)
at
org.mockito.internal.creation.bytebuddy.MockMethodAdvice$RealMethodCall.invoke(MockMethodAdvice.java:234)
at
org.mockito.internal.invocation.InterceptedInvocation.callRealMethod(InterceptedInvocation.java:142)
at
org.mockito.internal.stubbing.answers.CallsRealMethods.answer(CallsRealMethods.java:45)
at org.mockito.Answers.answer(Answers.java:90)
at
org.mockito.internal.handler.MockHandlerImpl.handle(MockHandlerImpl.java:111)
at
org.mockito.internal.handler.NullResultGuardian.handle(NullResultGuardian.java:29)
at
org.mockito.internal.handler.InvocationNotifierHandler.handle(InvocationNotifierHandler.java:34)
at
org.mockito.internal.creation.bytebuddy.MockMethodInterceptor.doIntercept(MockMethodInterceptor.java:82)
at
org.mockito.internal.creation.bytebuddy.MockMethodAdvice.handle(MockMethodAdvice.java:134)
at
org.apache.pulsar.broker.namespace.NamespaceService.unloadNamespaceBundle(NamespaceService.java:839)
at
org.apache.pulsar.broker.namespace.NamespaceService.unloadNamespaceBundle(NamespaceService.java:830)
at
java.lang.invoke.LambdaForm$DMH/0x00007fd54cb6cc00.invokeVirtual([email protected]/LambdaForm$DMH)
at
java.lang.invoke.LambdaForm$MH/0x00007fd54cb71000.invoke([email protected]/LambdaForm$MH)
at
java.lang.invoke.LambdaForm$MH/0x00007fd54cb70000.invoke([email protected]/LambdaForm$MH)
at
java.lang.invoke.Invokers$Holder.invokeExact_MT([email protected]/Invokers$Holder)
at
java.lang.invoke.MethodHandle.invokeWithArguments([email protected]/MethodHandle.java:733)
at
org.mockito.internal.util.reflection.InstrumentationMemberAccessor$Dispatcher$ByteBuddy$23hKbhcU.invokeWithArguments(Unknown
Source)
at
org.mockito.internal.util.reflection.InstrumentationMemberAccessor.invoke(InstrumentationMemberAccessor.java:251)
at
org.mockito.internal.util.reflection.ModuleMemberAccessor.invoke(ModuleMemberAccessor.java:55)
at
org.mockito.internal.creation.bytebuddy.MockMethodAdvice.tryInvoke(MockMethodAdvice.java:314)
at
org.mockito.internal.creation.bytebuddy.MockMethodAdvice$RealMethodCall.invoke(MockMethodAdvice.java:234)
at
org.mockito.internal.invocation.InterceptedInvocation.callRealMethod(InterceptedInvocation.java:142)
at
org.mockito.internal.stubbing.answers.CallsRealMethods.answer(CallsRealMethods.java:45)
at org.mockito.Answers.answer(Answers.java:90)
at
org.mockito.internal.handler.MockHandlerImpl.handle(MockHandlerImpl.java:111)
at
org.mockito.internal.handler.NullResultGuardian.handle(NullResultGuardian.java:29)
at
org.mockito.internal.handler.InvocationNotifierHandler.handle(InvocationNotifierHandler.java:34)
at
org.mockito.internal.creation.bytebuddy.MockMethodInterceptor.doIntercept(MockMethodInterceptor.java:82)
at
org.mockito.internal.creation.bytebuddy.MockMethodAdvice.handle(MockMethodAdvice.java:134)
at
org.apache.pulsar.broker.namespace.NamespaceService.unloadNamespaceBundle(NamespaceService.java:830)
at
org.apache.pulsar.broker.service.BrokerService.lambda$unloadNamespaceBundlesGracefully$30(BrokerService.java:999)
at
org.apache.pulsar.broker.service.BrokerService$$Lambda/0x00007fd54cb6ef58.accept(Unknown
Source)
at java.lang.Iterable.forEach([email protected]/Iterable.java:75)
at
org.apache.pulsar.broker.service.BrokerService.unloadNamespaceBundlesGracefully(BrokerService.java:992)
at
org.apache.pulsar.broker.service.BrokerService.unloadNamespaceBundlesGracefully(BrokerService.java:962)
at
org.apache.pulsar.broker.PulsarService.closeAsync(PulsarService.java:525)
at
java.lang.invoke.DirectMethodHandle$Holder.invokeVirtual([email protected]/DirectMethodHandle$Holder)
at
java.lang.invoke.LambdaForm$MH/0x00007fd54c488000.invoke([email protected]/LambdaForm$MH)
at
java.lang.invoke.LambdaForm$MH/0x00007fd54c488400.invoke([email protected]/LambdaForm$MH)
at
java.lang.invoke.Invokers$Holder.invokeExact_MT([email protected]/Invokers$Holder)
at
java.lang.invoke.MethodHandle.invokeWithArguments([email protected]/MethodHandle.java:733)
at
org.mockito.internal.util.reflection.InstrumentationMemberAccessor$Dispatcher$ByteBuddy$23hKbhcU.invokeWithArguments(Unknown
Source)
at
org.mockito.internal.util.reflection.InstrumentationMemberAccessor.invoke(InstrumentationMemberAccessor.java:251)
at
org.mockito.internal.util.reflection.ModuleMemberAccessor.invoke(ModuleMemberAccessor.java:55)
at
org.mockito.internal.creation.bytebuddy.MockMethodAdvice.tryInvoke(MockMethodAdvice.java:314)
at
org.mockito.internal.creation.bytebuddy.MockMethodAdvice$RealMethodCall.invoke(MockMethodAdvice.java:234)
at
org.mockito.internal.invocation.InterceptedInvocation.callRealMethod(InterceptedInvocation.java:142)
at
org.mockito.internal.stubbing.answers.CallsRealMethods.answer(CallsRealMethods.java:45)
at org.mockito.Answers.answer(Answers.java:90)
at
org.mockito.internal.handler.MockHandlerImpl.handle(MockHandlerImpl.java:111)
at
org.mockito.internal.handler.NullResultGuardian.handle(NullResultGuardian.java:29)
at
org.mockito.internal.handler.InvocationNotifierHandler.handle(InvocationNotifierHandler.java:34)
at
org.mockito.internal.creation.bytebuddy.MockMethodInterceptor.doIntercept(MockMethodInterceptor.java:82)
at
org.mockito.internal.creation.bytebuddy.MockMethodAdvice.handle(MockMethodAdvice.java:134)
at
org.apache.pulsar.broker.PulsarService.closeAsync(PulsarService.java:509)
at org.apache.pulsar.broker.PulsarService.close(PulsarService.java:484)
at
java.lang.invoke.LambdaForm$DMH/0x00007fd54c2d2000.invokeVirtual([email protected]/LambdaForm$DMH)
at
java.lang.invoke.LambdaForm$MH/0x00007fd54c528000.invoke([email protected]/LambdaForm$MH)
at
java.lang.invoke.LambdaForm$MH/0x00007fd54c488400.invoke([email protected]/LambdaForm$MH)
at
java.lang.invoke.Invokers$Holder.invokeExact_MT([email protected]/Invokers$Holder)
at
java.lang.invoke.MethodHandle.invokeWithArguments([email protected]/MethodHandle.java:733)
at
org.mockito.internal.util.reflection.InstrumentationMemberAccessor$Dispatcher$ByteBuddy$23hKbhcU.invokeWithArguments(Unknown
Source)
at
org.mockito.internal.util.reflection.InstrumentationMemberAccessor.invoke(InstrumentationMemberAccessor.java:251)
at
org.mockito.internal.util.reflection.ModuleMemberAccessor.invoke(ModuleMemberAccessor.java:55)
at
org.mockito.internal.creation.bytebuddy.MockMethodAdvice.tryInvoke(MockMethodAdvice.java:314)
at
org.mockito.internal.creation.bytebuddy.MockMethodAdvice$RealMethodCall.invoke(MockMethodAdvice.java:234)
at
org.mockito.internal.invocation.InterceptedInvocation.callRealMethod(InterceptedInvocation.java:142)
at
org.mockito.internal.stubbing.answers.CallsRealMethods.answer(CallsRealMethods.java:45)
at org.mockito.Answers.answer(Answers.java:90)
at
org.mockito.internal.handler.MockHandlerImpl.handle(MockHandlerImpl.java:111)
at
org.mockito.internal.handler.NullResultGuardian.handle(NullResultGuardian.java:29)
at
org.mockito.internal.handler.InvocationNotifierHandler.handle(InvocationNotifierHandler.java:34)
at
org.mockito.internal.creation.bytebuddy.MockMethodInterceptor.doIntercept(MockMethodInterceptor.java:82)
at
org.mockito.internal.creation.bytebuddy.MockMethodAdvice.handle(MockMethodAdvice.java:134)
at org.apache.pulsar.broker.PulsarService.close(PulsarService.java:484)
at
org.apache.pulsar.broker.testcontext.PulsarTestContext$StartableCustomBuilder.lambda$initializePulsarServices$0(PulsarTestContext.java:779)
at
org.apache.pulsar.broker.testcontext.PulsarTestContext$StartableCustomBuilder$$Lambda/0x00007fd54c521b70.close(Unknown
Source)
at
org.apache.pulsar.broker.testcontext.PulsarTestContext.callCloseables(PulsarTestContext.java:218)
at
org.apache.pulsar.broker.testcontext.PulsarTestContext.close(PulsarTestContext.java:212)
at
org.apache.pulsar.broker.auth.MockedPulsarServiceBaseTest.internalCleanup(MockedPulsarServiceBaseTest.java:292)
at
org.apache.pulsar.client.impl.TopicsConsumerImplTest.cleanup(TopicsConsumerImplTest.java:108)
at
java.lang.invoke.LambdaForm$DMH/0x00007fd54c2d2000.invokeVirtual([email protected]/LambdaForm$DMH)
at
java.lang.invoke.LambdaForm$MH/0x00007fd54c400400.invoke([email protected]/LambdaForm$MH)
at
java.lang.invoke.Invokers$Holder.invokeExact_MT([email protected]/Invokers$Holder)
at
jdk.internal.reflect.DirectMethodHandleAccessor.invokeImpl([email protected]/DirectMethodHandleAccessor.java:153)
at
jdk.internal.reflect.DirectMethodHandleAccessor.invoke([email protected]/DirectMethodHandleAccessor.java:103)
at java.lang.reflect.Method.invoke([email protected]/Method.java:580)
at
org.testng.internal.invokers.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:139)
at
org.testng.internal.invokers.MethodInvocationHelper.invokeMethodConsideringTimeout(MethodInvocationHelper.java:69)
at
org.testng.internal.invokers.ConfigInvoker.invokeConfigurationMethod(ConfigInvoker.java:361)
at
org.testng.internal.invokers.ConfigInvoker.invokeConfigurations(ConfigInvoker.java:296)
at
org.testng.internal.invokers.TestInvoker.runConfigMethods(TestInvoker.java:823)
at
org.testng.internal.invokers.TestInvoker.runAfterConfigurations(TestInvoker.java:792)
at
org.testng.internal.invokers.TestInvoker.invokeMethod(TestInvoker.java:768)
at
org.testng.internal.invokers.TestInvoker.invokeTestMethod(TestInvoker.java:221)
at
org.testng.internal.invokers.MethodRunner.runInSequence(MethodRunner.java:50)
at
org.testng.internal.invokers.TestInvoker$MethodInvocationAgent.invoke(TestInvoker.java:969)
at
org.testng.internal.invokers.TestInvoker.invokeTestMethods(TestInvoker.java:194)
at
org.testng.internal.invokers.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:148)
at
org.testng.internal.invokers.TestMethodWorker.run(TestMethodWorker.java:128)
at org.testng.TestRunner$$Lambda/0x00007fd54c2eded8.accept(Unknown
Source)
at java.util.ArrayList.forEach([email protected]/ArrayList.java:1596)
at org.testng.TestRunner.privateRun(TestRunner.java:829)
at org.testng.TestRunner.run(TestRunner.java:602)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:437)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:431)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:391)
at org.testng.SuiteRunner.run(SuiteRunner.java:330)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:95)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1256)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1176)
at org.testng.TestNG.runSuites(TestNG.java:1099)
at org.testng.TestNG.run(TestNG.java:1067)
at
org.apache.maven.surefire.testng.TestNGExecutor.run(TestNGExecutor.java:155)
at
org.apache.maven.surefire.testng.TestNGDirectoryTestSuite.executeSingleClass(TestNGDirectoryTestSuite.java:102)
at
org.apache.maven.surefire.testng.TestNGDirectoryTestSuite.executeLazy(TestNGDirectoryTestSuite.java:117)
at
org.apache.maven.surefire.testng.TestNGDirectoryTestSuite.execute(TestNGDirectoryTestSuite.java:86)
at
org.apache.maven.surefire.testng.TestNGProvider.invoke(TestNGProvider.java:137)
at
org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:385)
at
org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:162)
at
org.apache.maven.surefire.booter.ForkedBooter.run(ForkedBooter.java:507)
at
org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:495)
"PulsarTestContext-executor-OrderedExecutor-0-0":
at
org.apache.pulsar.broker.service.AbstractDispatcherSingleActiveConsumer.disconnectActiveConsumers(AbstractDispatcherSingleActiveConsumer.java)
- waiting to lock <0x000010003425fd70> (a
org.apache.pulsar.broker.service.persistent.PersistentDispatcherSingleActiveConsumer)
at
org.apache.pulsar.broker.service.persistent.PersistentSubscription.resetCursor(PersistentSubscription.java:856)
- locked <0x000010003425f350> (a
org.apache.pulsar.broker.service.persistent.PersistentSubscription)
at
org.apache.pulsar.broker.service.persistent.PersistentSubscription$6.findEntryComplete(PersistentSubscription.java:824)
at
org.apache.pulsar.broker.service.persistent.PersistentMessageFinder.findEntryComplete(PersistentMessageFinder.java:162)
at
org.apache.bookkeeper.mledger.impl.OpFindNewest.readEntryComplete(OpFindNewest.java:133)
at
org.apache.bookkeeper.mledger.impl.cache.RangeEntryCacheImpl$1.readEntriesComplete(RangeEntryCacheImpl.java:241)
at
org.apache.bookkeeper.mledger.impl.cache.PendingReadsManager$PendingRead.readEntriesComplete(PendingReadsManager.java:253)
- locked <0x000010003427f678> (a
org.apache.bookkeeper.mledger.impl.cache.PendingReadsManager$PendingRead)
at
org.apache.bookkeeper.mledger.impl.cache.PendingReadsManager$PendingRead.lambda$attach$0(PendingReadsManager.java:232)
at
org.apache.bookkeeper.mledger.impl.cache.PendingReadsManager$PendingRead$$Lambda/0x00007fd54cb0fc60.run(Unknown
Source)
at
org.apache.bookkeeper.common.util.SingleThreadExecutor.safeRunTask(SingleThreadExecutor.java:137)
at
org.apache.bookkeeper.common.util.SingleThreadExecutor.run(SingleThreadExecutor.java:107)
at
io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.lang.Thread.runWith([email protected]/Thread.java:1596)
at java.lang.Thread.run([email protected]/Thread.java:1583)
"broker-topic-workers-OrderedExecutor-0-0":
at
org.apache.bookkeeper.mledger.impl.cache.PendingReadsManager$PendingRead.addListener(PendingReadsManager.java)
- waiting to lock <0x000010003427f678> (a
org.apache.bookkeeper.mledger.impl.cache.PendingReadsManager$PendingRead)
at
org.apache.bookkeeper.mledger.impl.cache.PendingReadsManager.readEntries(PendingReadsManager.java:430)
at
org.apache.bookkeeper.mledger.impl.cache.RangeEntryCacheImpl.doAsyncReadEntriesByPosition(RangeEntryCacheImpl.java:416)
at
org.apache.bookkeeper.mledger.impl.cache.RangeEntryCacheImpl.asyncReadEntriesByPosition(RangeEntryCacheImpl.java:303)
at
org.apache.bookkeeper.mledger.impl.cache.RangeEntryCacheImpl.asyncReadEntry0(RangeEntryCacheImpl.java:282)
at
org.apache.bookkeeper.mledger.impl.cache.RangeEntryCacheImpl.asyncReadEntry(RangeEntryCacheImpl.java:264)
at
org.apache.bookkeeper.mledger.impl.ManagedLedgerImpl.asyncReadEntry(ManagedLedgerImpl.java:2180)
at
org.apache.bookkeeper.mledger.impl.ManagedLedgerImpl.internalReadFromLedger(ManagedLedgerImpl.java:2150)
at
org.apache.bookkeeper.mledger.impl.ManagedLedgerImpl.asyncReadEntries(ManagedLedgerImpl.java:1906)
at
org.apache.bookkeeper.mledger.impl.ManagedCursorImpl.asyncReadEntriesWithSkip(ManagedCursorImpl.java:871)
at
org.apache.bookkeeper.mledger.impl.ManagedCursorImpl.asyncReadEntriesWithSkipOrWait(ManagedCursorImpl.java:1024)
at
org.apache.bookkeeper.mledger.impl.ManagedCursorImpl.asyncReadEntriesOrWait(ManagedCursorImpl.java:997)
at
org.apache.pulsar.broker.service.persistent.PersistentDispatcherSingleActiveConsumer.readMoreEntries(PersistentDispatcherSingleActiveConsumer.java:387)
- locked <0x000010003425fd70> (a
org.apache.pulsar.broker.service.persistent.PersistentDispatcherSingleActiveConsumer)
at
org.apache.pulsar.broker.service.persistent.PersistentDispatcherSingleActiveConsumer.lambda$dispatchEntriesToConsumer$2(PersistentDispatcherSingleActiveConsumer.java:242)
at
org.apache.pulsar.broker.service.persistent.PersistentDispatcherSingleActiveConsumer$$Lambda/0x00007fd54cb4bc30.run(Unknown
Source)
at
org.apache.bookkeeper.common.util.SingleThreadExecutor.safeRunTask(SingleThreadExecutor.java:137)
at
org.apache.bookkeeper.common.util.SingleThreadExecutor.run(SingleThreadExecutor.java:113)
at
io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.lang.Thread.runWith([email protected]/Thread.java:1596)
at java.lang.Thread.run([email protected]/Thread.java:1583)
Found 1 deadlock.
```
### Modifications
- Run callbacks in PendingRead without a synchronization lock on the
PendingRead instance.
- Modify the code to make a copy of the listeners/callbacks so that
synchronization isn't needed.
- Refactor PendingRead and replace single "boolean completed" with a state
field.
### Documentation
<!-- DO NOT REMOVE THIS SECTION. CHECK THE PROPER BOX ONLY. -->
- [ ] `doc` <!-- Your PR contains doc changes. -->
- [ ] `doc-required` <!-- Your PR changes impact docs and you will update
later -->
- [x] `doc-not-needed` <!-- Your PR changes do not impact docs -->
- [ ] `doc-complete` <!-- Docs have been already added -->
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]