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
SOCKET changes (CSocket RAII etc.) #4348
Conversation
fDisconnect = true; | ||
if (hSocket != INVALID_SOCKET) |
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.
Don't remove this check! hSocket can be INVALID_SOCKET if there is currently no connection open, in which case no closing needs to be done either.
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.
That check could then perhaps be rewritten to?
if (closesocket(hSocket) != WSAENOTSOCK) LogPrint("net", "disconnecting node %s\n", addrName);
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.
That would work. But I like the previous, explicit check better. It's just more clear "close the socket when we're connected" versus "try closing and log a message if it fails".
IMHO we should get rid of myclosesocket and the crazy construction in compat.h and make it a pure compatibility wrapper (only defined on unix), without extra functionality and checks. |
@laanwj I reworked our closesocket() to only be active on Non-Windows OSes, Windows now uses the pure API call. |
inline int myclosesocket(SOCKET& hSocket) | ||
#ifndef WIN32 | ||
// Emulate WIN32 closesocket() behaviour for other OSes | ||
inline int closesocket(SOCKET& hSocket) |
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 can be just SOCKET hSocket
now like a normal parameter, no need for it to be a reference anymore :)
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.
Isn't a reference better because we then use no extra 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.
For large types such as structures and objects that can be true (but then we'd use a const reference). For small types like integers and handles it's only overhead. On 64-bit architectures a pointer to an integer is larger than the integer itself.
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.
Understood and will be changed :).
The hard part now will be checking all existing closesocket() calls and determining if they should be followed by |
If you mind looking at #3461 and we can get that merged, it would remove quite a few of them ;). Also the closesocket() during network init for listen sockets should be easy, which is also true for socks5(). Not sure if there are that many left then... |
Hmm, thinking further about this, another way would be to define a CSocket class with move semantics (and a method |
I like the idea of a RAII wrapper for sockets. |
@sipa @laanwj I started implementing CSocket, can you give me some feedback and help to see if I'm on the right track please :). See: https://github.com/Diapolo/bitcoin/commit/1c5873e0ba4cc466c11e5a0dbc779d78b5662075 Edit: The new class is currently only used for listening sockets to show the current implementation state. |
@laanwj @sipa Alright, I was able to fix the problems from last night. During BOOST_FOREACH processing existing sockets were copied/used and got closed by the destructor after the loop ^^. This is now fixed by a new flag Commit is at: https://github.com/Diapolo/bitcoin/commit/079dab40b8e2d88786d2fd0bef9025afa5719b9d |
I'm going for some incremental pulls that are included here, see #4388 for the first one. |
Did anyone take a look at the RAII class yet? I don't want to continue, if it's bugged or it's implementation is not correct. |
If we are going to have an RAII CSocket, we might as well add classes Connection, SocketServer, IOEngine. Then we can ditch boost::asio for the RPC server, and use that instead. |
@Diapolo No, haven't got around to it. @jgarzik I disagree we should be spending time writing and maintaining our own asynchronous I/O library. It's not like we're innovating anything here. If we want to ditch boost::asio we should switch to something which is well-known to be robust and high-performance like libevent (or derivatives). |
If we don't want our own async I/O lib, then adding RAII CSocket is moving in the wrong direction. boost::asio already has portable socket classes and much much more. |
Well - in principle I agree that using the same network library everywhere would be a good thing. But I know at least @gmaxwell doesn't like boost::asio and doesn't want to switch the P2P code to it. So at some point we have to make a decision about what async networking library to use. Not necessarily now. The point here was to get rid of the strange compat.h behavior - a compatibility wrapper should provide compatibility not add functionality. I then thought, if we're changing socket closing behavior we might as well make it RAII. But if that's a stap too far, fair enough... |
@laanwj Thinking about |
@Diapolo Well in cases where the purpose of the Logprintf is to log the error it should definitely be logged before the close, otherwise it will log the status of the close(). In other cases it doesn't matter what you do first. |
@laanwj Right, it's only relevant, when a call to |
Did anyone look at the RAII wrapper yet or is this considered unhelpful in the end? |
@Diapolo I've looked at it and it looks okay, but as @jgarzik says it may be too much if we intend to move to some other async networking library for P2P. Although it is clearly the way forward - from another async networking library we'd expect nothing less - right now it may brings subtle new bugs that have to be debugged. So I prefer the more trivial change in #4504 for now. |
Simpler alternative to bitcoin#4348. The current setup with closesocket() is strange. It poses as a compatibility wrapper but adds functionality. Rename it and make it a documented utility function in netbase. Code movement only, zero effect on the functionality.
- call CloseSocket() before printing any text (ensure consistent usage in the code), exception is when using NetworkErrorString()
@laanwj I reworked and rethought this, there is no need to try to emulate WIN32 |
CSocket seems to add never-used methods and flags. |
@jgarzik Right, the ones who are unused are |
Automatic sanity-testing: PASSED, see http://jenkins.bluematt.me/pull-tester/p4348_684bec2f41d0963fe24cf55cd397b962a25529cf/ for binaries and test log. |
The move semantics seem important. Right now you can copy or assign a socket and have two sockets using the same handle; then if one goes out of scope or is Putting the "whitelisted" flag in what would otherwise be a general RAII socket wrapper seems odd. Why not keep the Having the |
@kazcw I guess I need some more help to implement what you suggest about disallow cloning. Makes sense that no CSocket should have the same handle. How can this be achieved? |
To prevent copying, you can declare a private copy constructor with no implementation. vhListenSocket would need to be a vector of pointers. |
As said before, I deem the RAII changes too risky for what it would bring and am not going to merge it, sorry. This would make sense as part of a change that wraps all networking behavior in proper classes, but if we make such a high-impact change to networking we should consider switching to an existing high-performance async networking library instead of mucking about with our own. Something to consider in the future, but right now there are much more pressing things. |
Simpler alternative to bitcoin#4348. The current setup with closesocket() is strange. It poses as a compatibility wrapper but adds functionality. Rename it and make it a documented utility function in netbase. Code movement only, zero effect on the functionality.
Simpler alternative to bitcoin#4348. The current setup with closesocket() is strange. It poses as a compatibility wrapper but adds functionality. Rename it and make it a documented utility function in netbase. Code movement only, zero effect on the functionality. (cherry picked from commit 43f510d) # Conflicts: # src/netbase.cpp
-- call CloseSocket() before printing any text (ensure consistent
usage in the code), exception is when using NetworkErrorString()