-
Notifications
You must be signed in to change notification settings - Fork 38.7k
Avoid locking CTxMemPool::cs recursively in some cases #19872
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
|
Updated c22c4d2 -> e79bc0f (pr19872.01 -> pr19872.02, diff):
|
|
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ConflictsReviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first. |
|
Rebased e79bc0f -> 2a3e7cb (pr19872.02 -> pr19872.03) due to the conflict with #19848. |
|
Rebased 2a3e7cb -> f594b9a (pr19872.03 -> pr19872.04) due to the conflicts with #19478 and #19556. |
No change in behavior, some call sites already held the lock and a lock is added in the remaining sites.
No change in behavior, some call sites already held the lock and a lock is added in the remaining sites.
No change in behavior, some call sites already held the lock and a lock is added in the remaining sites.
No change in behavior, some call sites already held the lock and a lock is added in the remaining sites.
No change in behavior, some call sites already held the lock and a lock is added in the remaining sites.
No change in behavior, some call sites already held the lock and a lock is added in the remaining sites.
No change in behavior, some call sites already held the lock and a lock is added in the remaining sites.
No change in behavior, some call sites already held the lock and a lock is added in the remaining sites.
No change in behavior, some call sites already held the lock and a lock is added in the remaining sites.
No change in behavior, some call sites already held the lock and a lock is added in the remaining sites.
|
Rebased f594b9a -> ff19c7d (pr19872.04 -> pr19872.05) due to the conflict with #19791. |
jnewbery
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.
I've reviewed the first three commits, and I'm not sure this is the right direction. Adding locks to lots of places outside the mempool seems unnecessary.
| void CTxMemPool::check(const CCoinsViewCache *pcoins) const | ||
| { | ||
| LOCK(cs); | ||
| AssertLockHeld(cs); |
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.
I don't understand why this change is necessary. check() is never currently called with the lock held.
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.
It is here (mutex locked a little bit earlier).
| void CTxMemPool::check(const CCoinsViewCache *pcoins) const | ||
| { | ||
| LOCK(cs); | ||
| AssertLockHeld(cs); |
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.
I don't think this change is necessary. check() isn't currently called anywhere with the lock held.
| LOCK(cs); | ||
| void CTxMemPool::GetTransactionAncestry(const uint256& txid, size_t& ancestors, size_t& descendants) const | ||
| { | ||
| AssertLockHeld(cs); |
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.
Again, I don't think this change is necessary. GetTransactionAncestry() is only called with the lock held in the tests, which can be updated.
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.
Right, I also saw that. I guess @hebasto preferred this approach because the changes to tests would be too big and ugly? (if we mandate that GetTransactionAncestry() will lock the mutex itself and the callers should not be holding it)
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.
@vasild Correct.
promag
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.
IMO we should move the lock up the stack if it prevents unnecessary unlocks/locks. That's not the case, for instance in CTxMemPool::exists. Looks like it's a premature change.
|
Concept ACK. Similar changes are justified, assuming we want to get rid of recursive mutexes. Recursive mutexes are used by functions that need to own a mutex to do their stuff, but some of the callers of those functions own the mutex and some don't. So the function does not have a clear interface wrt the mutex, rather it has a vague interface like "the caller may own the mutex and I will lock it myself anyway". IMO the cleaner interface is if the mutex is acquired inside the function and none of the callers own it. If that is not possible then the function must not lock it and mandate that the callers own it. If that is too verbose for the callers, then two functions could be used - one that locks and another that does not: funcUnprotected() EXCLUSIVE_LOCKS_REQUIRED(cs)
{
AssertLockHeld(cs);
...
}
func() EXCLUSIVE_LOCKS_REQUIRED(!cs)
{
LOCK(cs);
funcUnprotected();
} |
|
Many thanks to @jnewbery, @promag and @vasild for your attention to thread safety design! Let me summarize the two approaches to preventing recursive locking of a mutex that are suggested/discussed/used in the repo:
I believe we should reach the consensus about approach we will use while migrating from Is it a topic for meeting? |
|
Sure! I just described variants when this is not possible :) |
Lines 755 to 761 in 147d50d
and |
|
For unit tests also there is @MarcoFalke's approach (fad3a7c5b9118d4d190401c0fbbd3e2068dffadc from #19909) to subclass |
|
🐙 This pull request conflicts with the target branch and needs rebase. Want to unsubscribe from rebase notifications on this pull request? Just convert this pull request to a "draft". |
This is another step (after #19854) to transit
CTxMemPool::csfromRecursiveMutextoMutex.Split out from #19306.
Thread safety annotations, lock assertions, and required explicit locking added. No behavior change.
Please note that now, since #19668 has been merged, it is safe to apply
AssertLockHeld()macros as they do not swallow compile time Thread Safety Analysis warnings.