-
Notifications
You must be signed in to change notification settings - Fork 37.7k
Do not hold cs_vNodes when making ForEachNode Callbacks #10697
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
Do not hold cs_vNodes when making ForEachNode Callbacks #10697
Conversation
hm this may require carefully auditing every use to determine if the code in question isn't being protected by an assumed holding of cs_vnodes. |
Indeed. I believe it is the case that none of them are needed, but I may be incorrect. Note that folks may want to hold off on review, @cfields indicated he may have a more complete solution to the general mess that is our manual CNode refcounting. |
No, please go ahead and review. I've worked on this several times now and haven't come up with anything that could be considered an improvement. I'm currently taking another look, but that shouldn't block this unless I manage to come up with something in the next day or so. |
Ping @theuni @TheBlueMatt, are you working on this? |
src/net.cpp
Outdated
break; | ||
} | ||
} | ||
return found != nullptr && NodeFullyConnected(found) && func(found); | ||
bool res = found != nullptr && NodeFullyConnected(found) && func(found); |
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 still calls func
while cs_vNodes
is held. Is that intentional?
src/net.cpp
Outdated
} | ||
} | ||
for (CNode* node : vNodes_copy) { | ||
if (NodeFullyConnected(node)) |
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.
Nit: either {
}
around if body, or body on the same line (in multiple places).
e4f477b
to
7f1ae14
Compare
Addressed @sipa's comments. |
7f1ae14
to
8b4a18f
Compare
8b4a18f
to
50ef0b0
Compare
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.
utACK 50ef0b0
return found != nullptr && NodeFullyConnected(found) && func(found); | ||
bool res = false; | ||
if (found != nullptr) { | ||
res = NodeFullyConnected(found) && func(found); |
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 will leak reference count if func throws. Suggest using RAII helper to prevent this, see NodeRef in eeb85c6. NodeRef also simplifies the ForEachNode implementations there.
} | ||
|
||
void CConnman::ForEachNode(std::function<void (CNode* pnode)> func) | ||
{ | ||
std::vector<CNode*> vNodes_copy; |
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.
These should just call ForEachNodeThen with a null post functions so this code doesn't have to be repeated so many times. Again see eeb85c6.
#define LEAVE_CRITICAL_SECTION(cs) \ | ||
{ \ | ||
(cs).unlock(); \ | ||
LeaveCritical((void*)(&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.
This should just say LeaveCritical(&(cs)). cs should be parenthesized since it's a macro argument, and the cast is unneeded.
Superceded by #11604 |
Generally holding locks while making callbacks is a bad idea, and for my eventual per-CNodeState locks. Also makes DEBUG_LOCKORDER more strict in a way that it assumes so best to enforce the requirement that locks are released in the order they are taken.
These two commits were pulled out of #10652 as they were entirely unconnected from the rest. Note that there was already a comment on the ForEachNode commit there.