4

If I bind() an AF_INET socket (for a TCP connection), then later close() it, next time I run my program, I may have issues, since despite the close(), the kernel can still have the resources associated with the open socket.

I am not very clear on this issue with the Unix Domain Sockets, though.

So far I have seen

  1. I need a unique path to use it with bind(). The path must not exist at the time bind() is called, and the file will be created by bind(). (However, it may or may not be visible in the filesystem. The file will not appear in the filesystem, if the path starts with the special char \0.)

  2. If the file is not unlink()-ed, even after close, the kernel keeps the associated resources, and the socket is fully functional.

QUESTION:

Since neither close() nor unlink() alone can make a Unix Domain Socket disappear, will both of them do the trick reliably / trigger the kernel to give up all the resources associated with the socket?

Is it possible that I will ever run into a reuseaddr error, if both close() and unlink() were called?


EDIT (after the comments and answer):

So, a binded AF_LOCAL socket looks something like this:

unix_domain_socket_inode
-> binded to a socket
-> associated with a file (path)

The unix_domain_socket_inode will live as long as:

  1. something keeps it open (the socket is not closed), or
  2. it has the associated path

If only 1. is true, we have an open socket and an inode, and everything works.

If only 2. is true, since the inode has a path associated with it, the kernel cannot clean it up, but it does not work either, because it lacks the socket resources that handle incoming connections. It won't even be a normal file, just a dead husk of the past glory of a busy, working socket.

In case of the AF_INET connection, the address reuse issue was a design choice for better usability.

In case of the AF_LOCAL, the leftover file is an artifact from previous design choices, which prevent the kernel itself from automatically cleaning up the file it created in 1 go, when close() is called. There is no hidden mechanism associated, because of which the kernel would want to keep this resource after a close() is called.

  • 1
    I would test your assertion regarding unlink() From memory, its the inode not the file path which is technically listened to. This should mean that removing the file name and then listening to the same address should create a new inode, leave the old listening socket permanently hidden. – Philip Couling Apr 1 at 15:09
  • You really shouldn't say TCP socket, it's confusing – 炸鱼薯条德里克 Apr 1 at 15:27
  • 1
    The socket won't be fully functional. You can't bind to that address any more, once you bind and close without unlink the address, the address will stuck on your filesystem. Also unlink that path won't make uds disappear, it just make that address non-accessible, the address of a pathname uds is actually an inode, not an pathname. Please test it by yourself. But abstract uds automatically release the address after close. – 炸鱼薯条德里克 Apr 1 at 15:46
3

In this context, it's important to understand the rationale for why the kernel has the TIME_WAIT state for TCP connections. This state is intended to allow any packets associated with the connection (that may have taken longer routes or otherwise been delayed) to drain from the network before a new connection on the same port can be established. That way, you ensure that a new connection doesn't receive any packets associated with the old connection. The reuseaddr option enables the developer to communicate "don't perform that wait".

Unix domain sockets don't have that concern; reuseaddr doesn't really make sense in that context.

1

If the file is not unlink()-ed, even after close, the kernel keeps the associated resources, and the socket is fully functional.

No, the kernel will release all resources associated with the socket when the last open handle to it was close()d. You only need to unlink() the path in order to be able to bind() again to it.

Since neither close() nor unlink() alone can make a Unix Domain Socket disappear, will both of them do the trick reliably / trigger the kernel to give up all the resources associated with the socket?

See above ;-)

The unix_domain_socket_inode will live as long as:

  1. something keeps it open (the socket is not closed), or
  2. it has the associated path

No for 2. Its "associated path" could be removed (unlink()ed) and the socket could still be accessible through another hard link.

See my other answer for a demo and explanation.

You seem to confuse the socket inode (the one pointed by the actual socket fd and also accessible through /proc/PID/fd/FD) with the inode it may be bound to (a socket file like /tmp/.X11-unix/X0); they're different, and the latter is only used as an "entry point" -- as soon as the the socket bound to it is closed, the socket file is only a dummy inode in the file system.

The file will not appear in the filesystem, if the path starts with the special char \0.)

If .sun_path starts with \0, it's no longer a path, but an "abstract" unix domain address, which unlike paths may contain other \0 bytes and has quite different semantics (anybody can connect to the socket, unlike an old-style unix domain socket, where connecting to it is subject to the file access permissions determined by its leading path).

Beware that this "abstract socket" feature is only present in Linux.

  • Just for clarification, """No for 2. Its "associated path" could be removed (unlink()ed) and the socket could still be accessible through another hard link.""" here, for the 2. point was meant as the case when """the socket is closed, but the path (at least 1 path) associated with socket-inode - the unix_domain_socket_inode - is not unlinked.""". So Your answer here regards the case when the socket is not closed. You are right, my problem is exactly that I don't understand, where the socket resources end, and the file/inode resources begin. But these answers helped a lot! – Zoltan K. Apr 1 at 19:31
  • If the socket is closed, but the path it was bound to is left behind, it's just a dummy file that only prevents bind-ing to the same path again. – Uncle Billy Apr 1 at 19:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.