16

There's a great answer on StackOverflow about providing a better lock for daemons (synthesized from Eduardo Fleury) that doesn't depend on the common PID file lock mechanism for daemons. There are lots of good comments there about why PID lock files can sometimes cause problems, so I won't rehash them here.

In short, the solution relies on Linux abstract namespace domain sockets, which keeps track of the sockets by name for you, rather than relying on files, which can stick around after the daemon is SIGKILL'd. The example shows that Linux seems to free the socket once the process is dead.

But I can't find definitive documentation in Linux that says what exactly Linux does with the abstract socket when the bound process is SIGKILL'd. Does anyone know?

Put another way, when precisely is the abstract socket freed to be used again?

I don't want to replace the PID file mechanism with abstract sockets unless it definitively solves the problem.

3
  • 3
    I can't find anything that answers this directly. But since there's no API for removing abstract sockets, it seems like they would have to be managed automatically by the kernel. When there are no processes with the socket open, it should go away.
    – Barmar
    Jul 17, 2015 at 18:22
  • @Barmar Fair enough. Care to add it as an answer?
    – CivFan
    Jul 20, 2015 at 21:30
  • I would prefer to have more definite information.
    – Barmar
    Jul 20, 2015 at 21:48

2 Answers 2

7

I posted this question over a year ago and was never quite satisfied with the lack of definitive documentation. I thought I'd check Linux documentation again for any updates, and was happy to see this:

Abstract sockets

Socket permissions have no meaning for abstract sockets: the process umask(2) has no effect when binding an abstract socket, and changing the ownership and permissions of the object (via fchown(2) and fchmod(2)) has no effect on the accessibility of the socket.

Abstract sockets automatically disappear when all open references to the socket are closed.

Also, The Linux Programming Interface by Michael Kerrisk covers the question (cross-posted from this other answer):

57.6 The Linux Abstract Socket Namespace

The so-called abstract namespace is a Linux-specific feature that allows us to bind a UNIX domain socket to a name without that name being created in the file system. This provides a few potential advantages:

  • We don’t need to worry about possible collisions with existing names in the file system.
  • It is not necessary to unlink the socket pathname when we have finished using the socket. The abstract name is automatically removed when the socket is closed.
  • We don’t need to create a file-system pathname for the socket. This may be useful in a chroot environment, or if we don’t have write access to a file system.

To create an abstract binding, we specify the first byte of the sun_path field as a null byte (\0). [...]

I reckon that, along with @user3188445's answer, this clears the question up very precisely.

That said, there's still an assumption made here, that processes which are SIGKILL'd will have all open sockets closed. That seems a reasonable assumption, but I don't have documentation that defines that behavior.

2
  • 1
    Re last paragraph: sockets are file descriptors, and all open file descriptors are closed when a process exits. Ish. More specifically, a socket is an open file, open files can be passed around e.g. inherited by child processes. So you should make sure to call socket with SOCK_CLOEXEC in case any code (including a library) ever does fork()+exec(). Creating extra child processes using fork() without exec() is less common; you probably know already if you're doing that.
    – sourcejedi
    Jun 9, 2019 at 15:13
  • It is not necessary to unlink... - um, since there is no pathname, it's not possible to unlink, not just unnecessary.
    – domen
    Sep 19, 2019 at 10:35
6

Yes, linux automatically "cleans up" abstract sockets to the extent that cleaning up even makes sense. Here's a minimal working example with which you can verify this:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>

int
main(int argc, char **argv)
{
  int s;
  struct sockaddr_un sun;

  if (argc != 2 || strlen(argv[1]) + 1 > sizeof(sun.sun_path)) {
    fprintf(stderr, "usage: %s abstract-path\n", argv[0]);
    exit(1);
  }

  s = socket(AF_UNIX, SOCK_STREAM, 0);
  if (s < 0) {
    perror("socket");
    exit(1);
  }
  memset(&sun, 0, sizeof(sun));
  sun.sun_family = AF_UNIX;
  strcpy(sun.sun_path + 1, argv[1]);
  if (bind(s, (struct sockaddr *) &sun, sizeof(sun))) {
    perror("bind");
    exit(1);
  }
  pause();
}

Run this program as ./a.out /test-socket &, then run ss -ax | grep test-socket, and you will see the socket in use. Then kill %./a.out, and ss -ax will show the socket is gone.

However, the reason you can't find this clean-up in any documentation is that it isn't really cleaning up in the same sense that non-abstract unix-domain sockets need cleaning up. A non-abstract socket actually allocates an inode and creates an entry in a directory, which needs to be cleaned up in the underlying file system. By contrast, think of an abstract socket more like a TCP or UDP port number. Sure, if you bind a TCP port and then exit, that TCP port will be free again. But whatever 16-bit number you used still exists abstractly and always did. The namespace of port numbers is 1-65535 and never changes or needs cleaning.

So just think of the abstract socket name like a TCP or UDP port number, just picked from a much larger set of possible port numbers that happen to look like pathnames but are not. You can't bind the same port number twice (barring SO_REUSEADDR or SO_REUSEPORT). But closing the socket (explicitly or implicitly by terminating) frees the port, with nothing left to clean up.

2
  • It already passed the duck test. That's fine for some things, such as python, but I expect more for Linux kernel features. Take your examples of TCP / UDP ports -- there is plenty of documentation describing precisely when the port can be reused.
    – CivFan
    Aug 6, 2015 at 23:31
  • 2
    And why doesn't that documentation apply equally to abstract sockets? Do you have a reference? A better question might be where the extra clean-up complication for non-abstract Unix-domain sockets is documented. On my system, that's in unix(7), which says "Linux also supports an abstract namespace which is independent of the filesystem." So to me "independent of the filesystem" implies no file-system-specific cleanup. Aug 8, 2015 at 1:57

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .