Skip to content
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

[hotfix] fix data race in method drain() in TaskMailboxImpl.java #26219

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -243,11 +243,11 @@ private Mail takeOrNull(Deque<Mail> queue, int priority) {

@Override
public List<Mail> drain() {
List<Mail> drainedMails = new ArrayList<>(batch);
batch.clear();
Copy link
Contributor

@davidradl davidradl Feb 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we be eagerly grabbing the lock in all these methods so all processing is done under the lock? for example all references to batch should be under the lock as the value could change under us. I was thinking we could synchronize all the methods referencing batch, so we do not need the lock.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good idea that would solve all data races. However, I noticed that the current implementation seems to be acquiring locks depending on what thread is executing the method by invoking checkIsMailboxThread(). It might be that this was introduced for performance reasons; as acquiring the lock is a rather slow operation. But this is not entirely clear to me, as there are other methods like createBatch that acquire the lock even though the first instruction is to check is to ensure that only the mailbox thread is executing this.

This is why I reported only the data race on the drain method, as there is no instruction indicating that only the mailbox thread can execute that method.

final ReentrantLock lock = this.lock;
lock.lock();
try {
List<Mail> drainedMails = new ArrayList<>(batch);
batch.clear();
drainedMails.addAll(queue);
queue.clear();
hasNewMail = false;
Expand Down