NetEventsInterface’s methods and the lifetime of CNode objects in CConnman::m_nodes.
NetEventsInterface’s methods and the lifetime of CNode objects in CConnman::m_nodes.
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.
For details see: https://corecheck.dev/bitcoin/bitcoin/pulls/32278.
See the guideline for information on the review process.
| Type | Reviewers |
|---|---|
| Stale ACK | w0xlt |
If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.
Reviewers, 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.
Possible typos and grammar issues:
drahtbot_id_5_m
1091faf8ff...0f26ac35e2 and 0f26ac35e2...e44e669378: further elaborate how we safely access CNodes in m_nodes and how we avoid CNode destruction while it is being referenced.
ACK https://github.com/bitcoin/bitcoin/pull/32278/commits/e44e669378f2c63b09eda68797039b73047febff
Clear improvement in documentation.
1470+ * CNode objects keep a reference count that is used to avoid a destruction
1471+ * while the object is used. All users of elements from `m_nodes` must either
1472+ * do so while holding `m_nodes_mutex` or by incrementing the reference before
1473+ * use and decrement it after use. To make sure that a new reference is not added
1474+ * to a no-referenced CNode just before it is destroyed we use the following
1475+ * mechanism (without a help from the standard library):
I’d phrase this as:
Destroying objects from this list works as follows (see DisconnectNodes(), DeleteNode()):
m_nodes to m_nodes_disconnected, preventing future calls to ProcessMessages() and SendMessages() for this node, and decrementing the reference count<= 0 indicating there are no other references to this node in use (and hence no current calls to ProcessMessages or SendMessages)FinalizeNode() will be called to indicate the node is about to be destroyedCNode is deletedWhat do you mean with “(without a help from the standard library)”?
I meant without using shared_ptr, but surely we do use the standard library for other things. Removed this sentence altogether.
@ajtowns I took that wording, thanks! Since I copied it right away, I added you as co-author of the commit. Let me know if you do not want that.
1001@@ -1002,18 +1002,31 @@ class CNode
1002 };
1003
1004 /**
1005- * Interface for message handling
1006+ * Interface for message handling.
1007+ * For a given `CNode`, the methods must be called in the following order:
CNode, the methods will be called in the following order:”. (Both CNode and NetEventsInterface are interfaces the net module offers, so the appropriate documentation is how they work and what you need to do to implement NetEventsInterface, not how net.cpp needs to be implemented)
Document the requirements around the `NetEventsInterface`'s methods and
the lifetime of `CNode` objects in `CConnman::m_nodes`.
Co-authored-by: Anthony Towns <aj@erisian.com.au>
1484+ */
1485 std::vector<CNode*> m_nodes GUARDED_BY(m_nodes_mutex);
1486- std::list<CNode*> m_nodes_disconnected;
1487 mutable RecursiveMutex m_nodes_mutex;
1488+
1489+ std::list<CNode*> m_nodes_disconnected;
Perhaps document how we prevent concurrent access to this while you’re at it? (We can’t use GUARDED_BY(m_nodes_mutex) since that results in lock order issues with cs_main)
AIUI, accesses are:
DisconnectNodes() via ThreadSocketHandler() which adds nodes and removes them in normal operationStopNodes() via Stop() which runs it after StopThreads(), which ensures threadSocketHandler is joined before returning. Stop() is invoked in ~CConnman() and init.cpp:Shutdown()[EDIT: Adding a m_disconnected_nodes_mutex that is locked in ThreadSocketHandler() and StopNodes() would also be feasible afaics, though if we’re doing a rewrite just documenting why it works now also seems fine]
e44e669378...110548c9ea: take suggestions