RAII sockets: when to release (close)
Asked Answered
A

1

9

I want to write a simple, small C++ RAII wrapper over a C socket.

The question is in what state is a socket considered initialized (from the perspective of RAII) and so eligible for release.

For instance, for a TCP client socket: if the socket call succeed, but the connect call failed, should close be called?

This is just an example, I am interested in a general answer, something like:

  • Each socket successfully created by socket must be closed.
    or
  • There must be a close for each connect, listen or accept.

The man pages for socket & friends and close are not very clear (or at least to me).

Ate answered 27/4, 2015 at 17:38 Comment(6)
If you have a valid/active socket handle then it's been initialized.Stays
@CaptainObvlious When is a socket handle considered vaid/active?Ate
The socket handle is valid when socket or accept return a value other than INVALID_SOCKET and until you close the handle.Stays
@CaptainObvlious ty, I think this constitutes an answer.Ate
INVALID_SOCKET is a WinSock constant, @CaptainObvlious. In Unix tradition, Linux uses filedescriptors that are just indices into a zero-based array, so anything that is less than zero is a "faulty" return value from e.g. socket(). Oh, and checking for negative values fails for WinSock on 64 bits, because there the socket handle type is an unsigned integer, if I remember correctly (it's been a while, I must admit).Dope
One way to go is to make a very simple wrapper, that only calls close on desctruction of the wrapper object. It can also provide a manual close() for explicitly closing. This gives you a lot of control with little code, and you make sure you do not leak socket descriptors on exceptions.Tacy
D
3

The two parts to pair up for sockets are socket() with close() and connect() with shutdown(). As you see, it doesn't get as easy as with malloc() and free(). This is further complicated by the fact that not every socket is used to connect(), some also use bind() and accept() instead. However, if you call close() without shutdown(), it's just a forceful shutdown that is experienced as an error by the remote side, but you correctly release resources that were allocated.

I'd consider wrapping it twice, once to invoke close() and another time to invoke shutdown(). I wouldn't worry too much about the second part though, as failure to shutdown() is still mostly harmless.

Dope answered 27/4, 2015 at 17:47 Comment(1)
@bolov: As Ulrich says, you do not need to worry too much about calling shutdown as failing to do so will not leak resources. So I would not bother wrapping it with RAII. The rule on Unix is pretty simple: If any call returns a file descriptor >= 0 (open, socket, accept, dup...), you must close it to avoid a resource leak.Fiberboard

© 2022 - 2024 — McMap. All rights reserved.