3

If a unix socket is bound to a path, listen()s and do some work, after which it is closed, the socket "file" remains in the filesystem. But if I try to connect() to that path, I get

Connect errno:111
Connection refused

So what is left after the "artifact"? It is still an inode on filesystem (I can see it with ls), but it is not bound, not listening, and I cannot cat it, otherwise I get

cat: /tmp/unix.str: No such device or address

So what remains from the inode? And how can I make that "artifact" once more alive, bound and listening socket (without removing it, and creating fresh new socket with that path)?

  1. What is the purpose of "dead" local socket (why is it not remove after it was closed, when there is no usage with it anymore)?

  2. how can I revive the "dead" socket? (the main question)

  3. who is responsible for error connection refused? not being bind()ed or not listen()ing?

milanHrabos
  • 2,010
  • 3
  • 11
  • 45

1 Answers1

-1

You get "connection refused" when attempting to connect because nothing is listening on that local socket. It's the same as if you tried to make a connection to a TCP socket if nothing was listening on that port number.

Once the program that opened the socket is closed, it is the responsibility of that process to remove the file with unlink. The man page states:

Binding to a socket with a filename creates a socket in the filesystem that must be deleted by the caller when it is no longer needed (using unlink(2)). The usual UNIX close-behind semantics apply; the socket can be unlinked at any time and will be finally removed from the filesystem when the last reference to it is closed.

This of course could be a problem if the program crashes unexpectedly, so you could get around this by additionally using a lock file.

Another alternative is to use an abstract socket address. This is done by setting the first byte of sun_path in sockaddr_un to 0 and the remaining bytes to a null terminated string specifying the socket name. For example:

struct sockaddr_un sun;
sun.sun_family = AF_UNIX;
sun.sun_path[0] = 0;
strcpy(sun.sunpath + 1, "mysocketname");

This gives you a named socket without a corresponding socket file in the filesystem. This socket will automatically go away once the socket descriptor is closed, so another socket may then be opened with that name.

dbush
  • 205,898
  • 23
  • 218
  • 273
  • I cannot re-bind the local socket, if it exists (`Bind errno:98; Address already in use`), so I have to first `unlink()`, the old (dead) socket, after which I can re-bind and listen to that path again. But that is the question, what is the purpose of the "dead" socket, and how can I revive the dead socket (make it listening again), without `unlink()` – milanHrabos Jan 29 '21 at 20:02
  • @milanHrabos See my edit. It must be `unlink`'ed. – dbush Jan 29 '21 at 20:17
  • So the abstract socket is not created as `inode` on a filesystem? If no, how could be "abstract" (not being physically on filesystem) referenced? How is its data buffered? if it is not a regular inode? – milanHrabos Jan 29 '21 at 20:35
  • @milanHrabos A socket descriptor in the filesystem isn't an actual file that contains buffered data. It's just a pointer to a data structure in the kernel that manages all of that. A socket with an abstract address is the same, it just doesn't have a corresponding external file. – dbush Jan 29 '21 at 20:38
  • after creating a socket (perhaps via the `socket()` function) then call `setsockopt()` I.E. `int enable = 1; if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) < 0) error("setsockopt(SO_REUSEADDR) failed");` Then the socket can be reused. [setsockopt](https://stackoverflow.com/questions/24194961/how-do-i-use-setsockoptso-reuseaddr) – user3629249 Jan 31 '21 at 02:38
  • @user3629249 That doesn't work for `AF_UNIX` sockets, only TCP or UDP. – dbush Jan 31 '21 at 02:40