Skip to content

Conversation

theStack
Copy link
Contributor

This PR is related to #19303 and gets rid of the following RecursiveMutex members in class CConnman:

  • for cs_totalBytesRecv, protecting nTotalBytesRecv, std::atomic is used instead (the member is only increment at one and read at another place, so this is sufficient)
  • for m_addr_fetches_mutex, protecting m_addr_fetches, a regular Mutex is used instead (there is no chance that within one critical section, another one is called)
  • for cs_vAddedNodes, protecting vAddedNodes, a regular Mutex is used instead (there is no chance that within one critical section, another one is called)

Additionally, the PR takes the chance to rename all node vector members (vNodes, vAddedNodes) and its corresponding mutexes (cs_vNodes, cs_vAddedNodes) to match the coding guidelines via a scripted-diff.

@theStack theStack force-pushed the 202108-refactor-recursive_mutex_replacements_in_cconnman branch 2 times, most recently from 829c50c to 94a99d0 Compare August 29, 2021 12:31
@DrahtBot
Copy link
Contributor

DrahtBot commented Aug 30, 2021

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Conflicts

Reviewers, this pull request conflicts with the following ones:

  • #21943 (Dedup and RAII-fy the creation of a copy of CConnman::vNodes by vasild)
  • #21879 (Wrap accept() and extend usage of Sock by vasild)
  • #21878 (Make all networking code mockable by vasild)

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.

Copy link
Contributor

@promag promag left a comment

Choose a reason for hiding this comment

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

Code review ACK 94a99d0.

@jonatack
Copy link
Member

jonatack commented Sep 6, 2021

Concept ACK and clang 13 debug build is clean.

@maflcko
Copy link
Member

maflcko commented Sep 6, 2021

there is no chance that within one critical section, another one is called

why? What prevents ForEachNode to call DisconnectNode or so via the lambda?

@maflcko
Copy link
Member

maflcko commented Sep 6, 2021

The scripted diff could be shortened with a rename helper like 37dcd12

@theStack
Copy link
Contributor Author

theStack commented Sep 6, 2021

there is no chance that within one critical section, another one is called

why? What prevents ForEachNode to call DisconnectNode or so via the lambda?

What concrete mutex are you referring to? Note that this PR only tackles the RecursiveMutex->Mutex replacement for vAddedNodes_cs (which is only locked in a small number of places, see commit log message for details), not vNodes_cs, which is a way more complex beast to beat.

The scripted diff could be shortened with a rename helper like 37dcd12

Good idea, will do in a bit.

@theStack theStack force-pushed the 202108-refactor-recursive_mutex_replacements_in_cconnman branch 2 times, most recently from 6ce979e to 6f0930a Compare September 6, 2021 13:18
@theStack
Copy link
Contributor Author

theStack commented Sep 6, 2021

Force-pushed with changed commit subject for the scripted-diff (using a helper), as suggested by MarcoFalke (#22829 (comment)):

$ git range-diff 94a99d05...6f0930a9
1:  cf29163ca ! 1:  887df8ecc scripted-diff: rename node vector/mutex members in CConnman
    @@ Commit message
         scripted-diff: rename node vector/mutex members in CConnman

         -BEGIN VERIFY SCRIPT-
    -    sed -i 's/cs_vAddedNodes/m_added_nodes_mutex/g' src/net.h src/net.cpp
    -    sed -i 's/vAddedNodes/m_added_nodes/g' src/net.h src/net.cpp
    -    sed -i 's/cs_vNodes/m_nodes_mutex/g' src/net.h src/net.cpp src/test/util/net.h
    -    sed -i 's/vNodesDisconnectedCopy/nodes_disconnected_copy/g' src/net.cpp
    -    sed -i 's/vNodesDisconnected/m_nodes_disconnected/g' src/net.h src/net.cpp
    -    sed -i 's/vNodesCopy/nodes_copy/g' src/net.cpp
    -    sed -i 's/vNodesSize/nodes_size/g' src/net.cpp
    -    sed -i 's/vNodes/m_nodes/g' src/net.h src/net.cpp src/test/util/net.h
    +
    +    ren() { sed -i "s/$1/$2/g" $3 $4 $5; }
    +
    +    ren cs_vAddedNodes         m_added_nodes_mutex     src/net.h src/net.cpp
    +    ren vAddedNodes            m_added_nodes           src/net.h src/net.cpp
    +    ren cs_vNodes              m_nodes_mutex           src/net.h src/net.cpp src/test/util/net.h
    +    ren vNodesDisconnectedCopy nodes_disconnected_copy src/net.cpp
    +    ren vNodesDisconnected     m_nodes_disconnected    src/net.h src/net.cpp
    +    ren vNodesCopy             nodes_copy              src/net.cpp
    +    ren vNodesSize             nodes_size              src/net.cpp
    +    ren vNodes                 m_nodes                 src/net.h src/net.cpp src/test/util/net.h
    +
         -END VERIFY SCRIPT-

      ## src/net.cpp ##
2:  5aca12d16 = 2:  73685d923 refactor: replace RecursiveMutex m_addr_fetches_mutex with Mutex
3:  94a99d05f = 3:  6f0930a96 refactor: replace RecursiveMutex m_added_nodes_mutex with Mutex

@DrahtBot DrahtBot mentioned this pull request Sep 29, 2021
12 tasks
Copy link
Contributor

@vasild vasild left a comment

Choose a reason for hiding this comment

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

ACK 6f0930a

Clang 12 build is clean with -Werror.

mutable RecursiveMutex cs_totalBytesSent;
uint64_t nTotalBytesRecv GUARDED_BY(cs_totalBytesRecv) {0};
std::atomic<uint64_t> nTotalBytesRecv{0};
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: might use std::atomic_uint64_t if it is available on all platforms that we aim to support.

Copy link
Member

Choose a reason for hiding this comment

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

std::atomic_uint64_t

The two are guaranteed to be the same either way.

Comment on lines -1880 to 1918
LOCK2(m_addr_fetches_mutex, cs_vAddedNodes);
if (m_addr_fetches.empty() && vAddedNodes.empty()) {
LOCK2(m_addr_fetches_mutex, m_added_nodes_mutex);
if (m_addr_fetches.empty() && m_added_nodes.empty()) {
add_fixed_seeds_now = true;
LogPrintf("Adding fixed seeds as -dnsseed=0, -addnode is not provided and all -seednode(s) attempted\n");
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Not necessary for this PR, but it is a good practice to avoid printouts (which may block) while holding mutexes. Feel free to take this or ignore it:

-                LOCK2(m_addr_fetches_mutex, m_added_nodes_mutex);
-                if (m_addr_fetches.empty() && m_added_nodes.empty()) {
-                    add_fixed_seeds_now = true;
+                {
+                    LOCK2(m_addr_fetches_mutex, m_added_nodes_mutex);
+                    add_fixed_seeds_now = m_addr_fetches.empty() && m_added_nodes.empty();
+                }
+                if (add_fixed_seeds_now) {
                     LogPrintf("Adding fixed seeds as -dnsseed=0, -addnode is not provided and all -see
                 }

@hebasto
Copy link
Member

hebasto commented Oct 8, 2021

Concept ACK.

Copy link
Member

@hebasto hebasto left a comment

Choose a reason for hiding this comment

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

ACK 6f0930a, I have reviewed the code, and verified that there are no ways to lock the mentioned mutexes recursivly.

Comment on lines +796 to +795
LOCK(m_added_nodes_mutex);
m_added_nodes = connOptions.m_added_nodes;
Copy link
Member

Choose a reason for hiding this comment

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

nit, could be

Suggested change
LOCK(m_added_nodes_mutex);
m_added_nodes = connOptions.m_added_nodes;
WITH_LOCK(m_added_nodes_mutex, m_added_nodes = connOptions.m_added_nodes);

without surrounding braces.

Mayby, better to leave it (and other similar places) for a follow up.

…stead

The RecursiveMutex cs_totalBytesRecv is only used at two places: in
CConnman::RecordBytesRecv() to increment the nTotalBytesRecv member, and in
CConnman::GetTotalBytesRecv() to read it. For this simple use-case, we can
make the member std::atomic instead to achieve the same result.
-BEGIN VERIFY SCRIPT-

ren() { sed -i "s/$1/$2/g" $3 $4 $5; }

ren cs_vAddedNodes         m_added_nodes_mutex     src/net.h src/net.cpp
ren vAddedNodes            m_added_nodes           src/net.h src/net.cpp
ren cs_vNodes              m_nodes_mutex           src/net.h src/net.cpp src/test/util/net.h
ren vNodesDisconnectedCopy nodes_disconnected_copy src/net.cpp
ren vNodesDisconnected     m_nodes_disconnected    src/net.h src/net.cpp
ren vNodesCopy             nodes_copy              src/net.cpp
ren vNodesSize             nodes_size              src/net.cpp
ren vNodes                 m_nodes                 src/net.h src/net.cpp src/test/util/net.h

-END VERIFY SCRIPT-
The RecursiveMutex m_addr_fetches_mutex is used at three places:
    - CConnman::AddAddrFetch()
    - CConnman::ProcessAddrFetch()
    - CConnman::ThreadOpenConnections()
In each of the critical sections, only the the m_addr_fetches is accessed
(and in the last case, also vAddedNodes), without any chance that within
one section another one is called. Hence, we can use an ordinary Mutex
instead of RecursiveMutex.
The RecursiveMutex m_added_nodes_mutex is used at three places:
    - CConnman::GetAddedNodeInfo()
    - CConnman::AddNode()
    - CConnman::ThreadOpenConnections()
In each of the critical sections, only the the m_added_nodes member is
accessed (and in the last case, also m_addr_fetches), without any chance
that within one section another one is called. Hence, we can use an
ordinary Mutex instead of RecursiveMutex.
@theStack theStack force-pushed the 202108-refactor-recursive_mutex_replacements_in_cconnman branch from 6f0930a to 3726a45 Compare November 24, 2021 18:52
Copy link
Contributor

@vasild vasild left a comment

Choose a reason for hiding this comment

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

ACK 3726a45

Copy link
Contributor

@promag promag left a comment

Choose a reason for hiding this comment

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

Code review ACK 3726a45.

Copy link
Member

@hebasto hebasto left a comment

Choose a reason for hiding this comment

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

re-ACK 3726a45

@maflcko maflcko merged commit 76392b0 into bitcoin:master Nov 25, 2021
@theStack theStack deleted the 202108-refactor-recursive_mutex_replacements_in_cconnman branch November 25, 2021 11:00
sidhujag pushed a commit to syscoin/syscoin that referenced this pull request Nov 25, 2021
@bitcoin bitcoin deleted a comment Nov 25, 2021
@bitcoin bitcoin locked and limited conversation to collaborators Nov 25, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants