-
Notifications
You must be signed in to change notification settings - Fork 3.7k
Use AtomicIntegerFieldUpdater to mutate volatile int totalAvailablePermits in PersistentDispatcherMultipleConsumers class #10180
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
This PR was co-authored with @devinbost . Thanks for @devinbost for pinpointing the code location around @codelipenghui @merlimat @eolivelli @rdhabalia Please review this change. |
|
btw. This problem was only in the Lines 94 to 148 in 31f8315
|
|
/pulsarbot run-failure-checks |
eolivelli
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
|
/pulsarbot run-failure-checks |
| closeFuture.complete(null); | ||
| } | ||
| totalAvailablePermits = 0; | ||
| TOTAL_AVAILABLE_PERMITS_UPDATER.set(this, 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would be equivalent to totalAvailablePermits = 0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
true. I tried to make it consistent with the style used in NonPersistentDispatcherMultipleConsumers:
Line 104 in 31f8315
| TOTAL_AVAILABLE_PERMITS_UPDATER.set(this, 0); |
| redeliveryTracker.addIfAbsent(PositionImpl.get(ledgerId, entryId)); | ||
| }); | ||
| totalAvailablePermits -= consumer.getAvailablePermits(); | ||
| TOTAL_AVAILABLE_PERMITS_UPDATER.addAndGet(this, -consumer.getAvailablePermits()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The increments/decrement on the totalAvailablePermits should already be safe because they're all done while holding the mutex on the dispatcher object.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes you are right, it seems that all updates are already happening withing synchronized methods.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@merlimat I re-opened this PR. readMoreEntries method isn't synchronized and it's getting called from this location without synchronization:
pulsar/pulsar-broker/src/main/java/org/apache/pulsar/broker/service/BrokerService.java
Lines 2439 to 2451 in a1cebdb
| public void unblockDispatchersOnUnAckMessages(List<PersistentDispatcherMultipleConsumers> dispatcherList) { | |
| lock.writeLock().lock(); | |
| try { | |
| dispatcherList.forEach(dispatcher -> { | |
| dispatcher.unBlockDispatcherOnUnackedMsgs(); | |
| executor().execute(() -> dispatcher.readMoreEntries()); | |
| log.info("[{}] Dispatcher is unblocked", dispatcher.getName()); | |
| blockedDispatchers.remove(dispatcher); | |
| }); | |
| } finally { | |
| lock.writeLock().unlock(); | |
| } | |
| } |
|
/pulsarbot run-failure-checks |
|
I'm closing this PR since as @merlimat pointed out, all mutations are already safe since they are done in |
…rmits - value can get corrupted if value is directly mutated
52e9d6c to
5f1f947
Compare
|
Currently PersistentStreamingDispatcherMultipleConsumers.readMoreEntries method isn't synchronized: Lines 137 to 140 in f2d72c9
Is there a reason why it's not a synchronized method? In one location the method is called within a synchronized block like this: Lines 191 to 205 in 31f8315
Synchronization is missing in this location: pulsar/pulsar-broker/src/main/java/org/apache/pulsar/broker/service/BrokerService.java Lines 2439 to 2451 in a1cebdb
|
|
Another location where the Lines 612 to 621 in 875262a
I'm running an experiment to see if tests pass when readEntries method is made |
|
I opened a separate PR #10413 to make the |
|
This PR is not needed since #10413 was merged. |
Motivation
AtomicIntegerFieldUpdater should be used to update
volatile intfields when the value is incremented or decremented. This prevents "lost update" issues.Modifications
Use existing
TOTAL_AVAILABLE_PERMITS_UPDATERto mutatetotalAvailablePermitsfield.Co-authored-by: Devin Bost devinbost@users.noreply.github.com