-
Notifications
You must be signed in to change notification settings - Fork 38.7k
refactor: wrap accept() and extend usage of Sock #21879
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
|
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. |
|
Concept ACK |
1 similar comment
|
Concept ACK |
|
|
|
|
|
|
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.
crACK tACK 9f04449
Thank you for helping decouple our tests from system calls, @vasild. I also ran tests, and manually tested incoming connections on regtest using:
# Start node0 with -listen
$ src/bitcoind -regtest -datadir=`pwd`/node0 -rpccookiefile=.cookie -port=2222 -rpcport=3333 -listen
# Generate a block on node0
$ src/bitcoin-cli -regtest -datadir=`pwd`/node0 -rpccookiefile=.cookie -rpcport=3333 createwallet test
$ src/bitcoin-cli -regtest -datadir=`pwd`/node0 -rpccookiefile=.cookie -rpcport=3333 -generate
# node0 has a block
$ src/bitcoin-cli -regtest -datadir=`pwd`/node0 -rpccookiefile=.cookie -rpcport=3333 getblockcount
1
$ src/bitcoin-cli -regtest -datadir=`pwd`/node0 -rpccookiefile=.cookie -rpcport=3333 getbestblockhash
1878296b74ee617ff119d2fc3f85c9fb35eae952e0360e505bb7d325dfe9e825
# Start node1
$ src/bitcoind -regtest -datadir=`pwd`/node1 -rpccookiefile=.cookie -port=2223 -rpcport=3334
# node1 has no blocks
$ src/bitcoin-cli -regtest -datadir=`pwd`/node1 -rpccookiefile=.cookie -rpcport=3334 getblockcount
0
# Restart node1 with -addnode=node0
$ src/bitcoind -regtest -datadir=`pwd`/node1 -rpccookiefile=.cookie -port=2223 -rpcport=3334 -addnode=127.0.0.1:2222
# node1 completes IBD and has the block
$ src/bitcoin-cli -regtest -datadir=`pwd`/node1 -rpccookiefile=.cookie -rpcport=3334 getblockcount
1
$ src/bitcoin-cli -regtest -datadir=`pwd`/node1 -rpccookiefile=.cookie -rpcport=3334 getbestblockhash
1878296b74ee617ff119d2fc3f85c9fb35eae952e0360e505bb7d325dfe9e825
Would the goal eventually be to not have to invoke Sock::Release() anywhere and instead use move semantics across the board as more code is RAII-fied?
| *addr_len = sizeof(sockaddr_in); | ||
| sockaddr_in* addr_in = reinterpret_cast<sockaddr_in*>(addr); | ||
| addr_in->sin_family = AF_INET; | ||
| memset(&addr_in->sin_addr, 0x05, sizeof(addr_in->sin_addr)); |
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): Would inet_pton(AF_INET, "5.5.5.5", &addr_in->sin_addr); be clearer?
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.
Yes, that would be clearer. However, some inet_...() function ended up using syscalls (it created sockets internally, IIRC) on Linux. @practicalswift, what do you think?
|
Very nice work. Non-blocking suggestion: Would it be possible to add a fuzzing harness utilizing |
Yes! #21878 removes
The |
jamesob
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.
ACK 9f04449 (jamesob/ackr/21879.1.vasild.wrap_accept_and_extend_u)
Change looks good to me and, as others have noted, making network code more mockable will make writing more comprehensive tests feasible. Cloned locally and ran unit, functional tests.
When I made the dumb mutation below, both test suites still passed so I guess we don't have any tests exercising socket errors.
diff --git a/src/util/sock.cpp b/src/util/sock.cpp
index 9a92fd1b5f..e25c1bab7f 100644
--- a/src/util/sock.cpp
+++ b/src/util/sock.cpp
@@ -76,7 +76,7 @@ std::unique_ptr<Sock> Sock::Accept(sockaddr* addr, socklen_t* addr_len) const
#ifdef WIN32
static constexpr auto ERR = INVALID_SOCKET;
#else
- static constexpr auto ERR = SOCKET_ERROR;
+ static constexpr auto ERR = SOCKET_ERROR + 1;
#endif
const auto socket = accept(m_socket, addr, addr_len);Show signature data
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512
ACK 9f04449a8ec7dc167a0d6d0cb47c5facd205a81a ([`jamesob/ackr/21879.1.vasild.wrap_accept_and_extend_u`](https://github.com/jamesob/bitcoin/tree/ackr/21879.1.vasild.wrap_accept_and_extend_u))
Change looks good to me and, as others have noted, making network code more mockable will make writing comprehensive tests more feasible. Cloned locally and ran unit, functional tests.
When I made the dumb mutation below, both test suites passed so I guess we don't have any tests exercising invalid socket errors.
<patch>
-----BEGIN PGP SIGNATURE-----
iQIzBAEBCgAdFiEEGNRVI1NPYuZCSIrGepNdrbLETwUFAmEgIVsACgkQepNdrbLE
TwWAvA/8C6OfGufmfaEdYzaaGVPyq1jmF7GmXsFo0T3AkflMBbMqri4Q+1ai1Yzs
CkVOuxGBDj8wiKxEeRsbsCsp3gbcOcp21ccvn6EQkPi0Mk8Rusj1iXgs+sDPuf7V
tKq3uQ54IbxkavKKWWhp5VeGrm4ddm8s2qF5uaN7UcGlGAPTw1915YW2HmEa3sC3
9hQb+VGw3nkczUBJXMZls0AUF6E8XYTX3QycSGjlpazgSJac5J54trfvdCzpR1Ae
0WlWndO/VROlePi6p2Mg0DHMCuuRyk78qCHx547WcaQxYWOic+XMEU1OELueLVbf
gf16So4iITHJWeK/GOLuecRfGm58uquWtQuzl5twzvPmzHRrwYyHrvgQP9eANzkQ
VCIbZWV7zL5ksgDGRJTwwzUERICvB6PqlzSU3a49f7kD2DnW+CMzHROe2YW+uLM7
lIn6fmw7WCLBAi990aOtlTf9eT4YYrkneNQYz4vnS/uWvNFBqrkCFxhTdBDHg0jr
8EDzNVFtBFnxKBLYia+ybnPb8pqqAak2AYlrpYVSw6NWSlaWLq8d5JwqkNjgY2K1
anpssdubMvHmWk+N5e0rFbRg1froCMB3Fn7BhbSRbNlnKecv1M+WE1UgI8Y4Hlcn
nLxE/xMFHD94q9N79b76ENqDN8lOgTQmIbUVVcW+LKJpZ5bIQnU=
=EpEl
-----END PGP SIGNATURE-----
Show platform data
Tested on Linux-4.19.0-17-amd64-x86_64-with-glibc2.28
Configured with ./configure LDFLAGS=-L/home/james/src/bitcoin/db4/lib/ CPPFLAGS=-I/home/james/src/bitcoin/db4/include/ CXXFLAGS=-fPIE -pipe -O2 -g -Wthread-safety-analysis -Wall -Werror=sign-compare --enable-wallet --with-daemon CXX=/usr/local/bin/clang++ CC=/usr/local/bin/clang --with-bignum=no PYTHONPATH= --disable-shared --with-pic --enable-benchmark=no --enable-module-recovery --enable-module-schnorrsig --enable-experimental --disable-shared --with-pic --enable-benchmark=no --enable-module-recovery --enable-module-schnorrsig --enable-experimental --no-create --no-recursion
Compiled with /usr/bin/ccache /usr/local/bin/clang++ -std=c++17 -mavx -mavx2 -fPIE -pipe -O2 -g -Wthread-safety-analysis -Wall -Werror=sign-compare -fdebug-prefix-map=$(abs_srcdir)=. -Wstack-protector -fstack-protector-all -fcf-protection=full -fstack-clash-protection -msse4 -msha -msse4.1 -msse4.2 i
Compiler version: Debian clang version 11.1.0-++20210428103820+1fdec59bffc1-1~exp1~20210428204437.162
|
@jamesob, thanks for looking into this! Your mod changes const auto socket = accept(m_socket, addr, addr_len);
if (socket == 0) {
return nullptr;
}
return std::make_unique<Sock>(socket);This will change the behavior in two cases:
I think it is unlikely that any of that happens (the real syscall |
|
@vasild yup, it was that second case I was curious about. Nothing wrong with this PR of course, just thought it might be interesting to note that we don't seem to have any coverage for the |
|
Right! |
|
This PR has 2 ACKs and 2 Concept ACKs. @practicalswift, @jonatack, willing to upgrade your "Concept ACK"s to full code review ACKs? |
|
Yes, I was reviewing this a few days ago when I hit the addrman corruption issue from the asmap/addrman init order. Back to it soon! |
jonatack
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.
|
Diff-review re-ACK 78e21e511ee241900b84d763462f26972d83b600 per |
jonatack
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.
re-ACK 0f4474d6da5741c7dc61cef403bb03faa2345f37 per git range-diff 2ef186a 07d998f 0f4474, re-review, rebase/debug build/ran units following my previous full review (#21879 (review))
This will help to increase `Sock` usage and make more code mockable.
Change `CConnman::ListenSocket` to use a pointer to `Sock` instead of a bare `SOCKET` and use `Sock::Accept()` instead of bare `accept()`. This will help mocking / testing / fuzzing more code.
Change `CConnman::CreateNodeFromAcceptedSocket()` to take a `Sock` argument instead of `SOCKET`. This makes the method mockable and also a little bit shorter as some `CloseSocket()` calls are removed (the socket will be closed automatically by the `Sock` destructor on early return).
jamesob
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.
ACK 6bf6e9f (jamesob/ackr/21879.2.vasild.wrap_accept_and_extend_u)
Examined interdiff and built/tested locally with a pre-populated datadir.
Changes since last review include rebasing on master (CJDNS changes, vNodes -> m_nodes), some && sock function sig changes, write_len rephrasing, and catching exceptions during unique_ptr construction in Sock::Accept.
Show signature data
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512
ACK 6bf6e9fd9dece67878595a5f3361851c25833c49 ([`jamesob/ackr/21879.2.vasild.wrap_accept_and_extend_u`](https://github.com/jamesob/bitcoin/tree/ackr/21879.2.vasild.wrap_accept_and_extend_u))
Examined interdiff and built/tested locally with a pre-populated datadir.
Changes since last review include rebasing on master (CJDNS changes, vNodes -> m_nodes), some
&& sock function sig changes, `write_len` rephrasing, and catching exceptions during unique_ptr
construction in Sock::Accept.
-----BEGIN PGP SIGNATURE-----
iQIzBAEBCgAdFiEEGNRVI1NPYuZCSIrGepNdrbLETwUFAmGn3PIACgkQepNdrbLE
TwXzpw/+KLFtcxY3gB2hbfsjsm0IUUiY/FWnFL1S5ADu5HaFAMHHkT9cEfCsMhAn
oQeGgtKJ4+kp3j01JEHwo7Sa/XLj1CEKWLbLd3OFJyFgQ7GJr0X9Ej0RmHN67Rjz
B70DzBNe6FeRz/tST+fkVOULLJqj0bwg1FeVMsHK1bbAWCtl358O25flNeXy5zCI
tY5IAevJII5RP1YjbeTddY5VRPXBNP/dohEL6M5mvZdNsz5/OHz7VfuCbJtH1LBC
E7HcaMl8y70feJ4bVHuRmupx1+TYy5JUx1Aj05EcNzmkC/APHdTcL9bsZXiiOeHU
nvp81Ozq7oRe9ZkEzTPiKScPP6rqHbFILUE+dYW22P6qjDczHdge2sPVzcyIWKMR
CW7tG9PSo4dzRly+jh8T90ApnPe7oVQr6pzPVTjAlyuNHcS7CWYnEWS0Nha1zWyv
TYV2jC/53ugrqVnUAm+HbfTR2SIhTpYgYpUkYArHmEyXL/PZOnYB02+vgEhTsMkQ
JSYHb7AwlHoKr9R+S7XvkNG2TN2/2x4XZNTYr8sDvdNlxWLzsfTbTv1g9gfX/U1U
VFvJNFUaY/i8qq0FUKYgHvz0JMvaoRnsTx5w1K4m9tvdiNtA34TJy+y1sP1VPnnr
7dA09N0rRu9BuAzioViAsd2eVZQS3TUOjvsYnKFL6EmsC/36lgg=
=HB8m
-----END PGP SIGNATURE-----
Show platform data
Tested on Linux-5.10.0-9-amd64-x86_64-with-glibc2.28
Configured with ./configure LDFLAGS=-L/home/james/src/bitcoin/db4/lib/ CPPFLAGS=-I/home/james/src/bitcoin/db4/include/ CXXFLAGS=-fPIE -pipe -O2 -g -Wthread-safety-analysis -Wall -Werror=sign-compare -Wsign-compare -Werror=thread-safety-analysis --enable-wallet --enable-debug --with-daemon --enable-natpmp-default CXX=/usr/bin/clang++ CC=/usr/bin/clang PYTHONPATH= --disable-openssl-tests --disable-shared --with-pic --enable-benchmark=no --enable-module-recovery --enable-module-schnorrsig --enable-experimental --disable-shared --with-pic --enable-benchmark=no --enable-module-recovery --enable-module-schnorrsig --enable-experimental --disable-openssl-tests --no-create --no-recursion
Compiled with /usr/bin/ccache /usr/bin/clang++ -std=c++17 -mavx -mavx2 -mpclmul -fPIE -pipe -O2 -g -Wthread-safety-analysis -Wall -Werror=sign-compare -Wsign-compare -Werror=thread-safety-analysis -O0 -g3 -ftrapv -fdebug-prefix-map=$(abs_top_srcdir)=. -Wstack-protector -fstack-protector-all -fcf-protection=full -fstack-clash-protection -msse4 -msha -msse4.1 -msse4.2 i
Compiler version: Debian clang version 13.0.1-++20211110052940+162f3f18c945-1~exp1~20211110053502.25
jonatack
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.
ACK 6bf6e9f per git range-diff ea989de 976f6e8 6bf6e9f -- only change since my last review was s/listen_socket.socket/listen_socket.sock->Get()/ in src/net.cpp: CConnman::SocketHandlerListening() -- re-read the code changes, rebase/debug build/ran units following my previous full review (#21879 (review))
|
Could maybe use another pair of eyes on this, but otherwise it seems RFM. |
|
It is unclear from the subject line and labels, but this is refactoring? It might be good to clarify that in the commit messages (if you need to push again) or at least in the pull request title and labels. This makes it easier for reviewers to see if it was accidental when it later turns out that this introduced any bugs or features. |
|
Yes, this is refactor since it does not change external behavior. Updated the PR title. I can't edit labels. |
w0xlt
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.
tACK 6bf6e9f
Ran the node on signet and the unit / functional tests.
Seems good. Sock::Accept encapsulates the accept() system call, making the code more mockable and simpler due to the use of the RAII Sock class.
If I understand correctly, instead of manually closing each socket from vhListenSocket, Sock destructor will automatically handle this after vhListenSocket.clear().
Yes! |
|
Code review ACK 6bf6e9f |
This is a piece of #21878, chopped off to ease review.
Introduce an
accept(2)wrapperSock::Accept()and extend the usage ofSockinCConnman::ListenSocketandCreateNodeFromAcceptedSocket().