-
Notifications
You must be signed in to change notification settings - Fork 6.4k
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
After encountering the problem of disk full, some write threads are stuck forever even though the disk has been cleaned up. #9692
Comments
an related issue #9762 for recovery after disk full. |
Also #9876. |
I only just familiarized myself with the code, but I agree with @zhuchong0329's analysis . In But the problem is, that So far I only analyzed the situation for pipelined writes, but I will also check the other code paths. |
I have created a unit test to systematically trigger this error. |
Thanks @zhuchong0329 for the analysis. I will need to check #9944 as well as @mpoeter 's comments in this thread to see if my question can be clarified. UPDATE: nvm, I think the comment above clarifies it. |
Good finding, one thread executes the same function twice allocates local object of the same type at the same address on the stack. |
Have you found anything? I looked at the non-pipelined write case, and the last writer in the group is completely unlinked, thus become unreachable via newest_writers_ before the newer writers are waken up, according to |
#9876 seems another occurrence because pipelined write is confirmed to be used in that case. |
Expected behavior
After disk cleanup, the write threads execute normally.
Actual behavior
After disk cleanup, the write threads are stuck forever.
In my environment,three write threads are stuck and their link_older is actually looped.
thread 1
thread 2
thread 3
their link_older is looped
Steps to reproduce the behavior
Why do these three writes form a ring? I think it is caused by the ABA problem of lock-free programming in the scenario where the disk is full.
An execution path of the conjecture that the three writes form a ring in the above case:
w1 becomes the leader in write group1, and w4 becomes the last writer in write group1.
w5 and w6 are successively added to the write linked list.
The execution of w1 encounters a disk full error and needs to notify other writes in write group 1. w4 was notified first and was removed from the write group.
w1 notifies other writes in turn.
The thread where w4 is located is awakened by w1, and continues to perform other write operations after returning an error. At this time, we name it w7. Unfortunately, the w7 object has the same address as the w4 object. w7 is added to the write list.
w1 notifies all writes in the write group, and then uses the recorded last writer to check whether newest_writer_ is updated. Unfortunately, the current newest_writer_ is consistent with last_writer, so newest_writer_ is set to nullptr.
w5, w6, w7 form a ring and are forever forgotten.
Where is the bug I think
In WriteThread::ExitAsBatchGroupLeader, it execute CompleteFollower first and then execute FindNextLeader When status is not ok. CompleteFollower will wake up the originally blocked Write thread, which may lead to ABA problems.
The text was updated successfully, but these errors were encountered: