The man page sem_overview(7)
explains that the name of named semaphores ought to start with /
. However, I couldn't find any specification of what should or would happen if such a name does not start by a slash.
Trying it out on Linux seems to reveal no difference at all and xxd /dev/shm/sem.mysem
also shows no difference when using sem_open("mysem", 0)
vs. sem_open("/mysem", 0)
in a (C) program.
Is the naming scheme actually of any relevance?
TLDR:
The GLIBC implementation ignores leading /
characters despite what the documentation says.
Full answer:
Per POSIX sem_open()
:
SYNOPSIS
#include <semaphore.h> sem_t *sem_open(const char *name, int oflag, ...);
DESCRIPTION
...
If
name
does not begin with the <slash> character, the effect is implementation-defined....
So, in this case the name will be treated per the Linux sem_open()
man page:
DESCRIPTION
sem_open()
creates a new POSIX semaphore or opens an existing semaphore. The semaphore is identified by name. For details of the construction of name, see sem_overview(7).
Which brings us back to the sem_overview(7)
man page as you noted:
Named semaphores
A named semaphore is identified by a name of the form /somename; that is, a null-terminated string of up to
NAME_MAX-4
(i.e., 251) characters consisting of an initial slash, followed by one or more characters, none of which are slashes.
As you noted, that doesn't specify what happens if the leading /
is omitted.
So, how is it implemented?
The actual name of the semaphore file (that's all a "POSIX named semaphore" is - a file in a file system that is memory mapped and contains a semaphore object) is created in GLIBC by the __shm_get_name()
function in the posix/shm-directory.c
file:
int
__shm_get_name (struct shmdir_name *result, const char *name, bool sem_prefix)
{
struct alloc_buffer buffer;
size_t namelen;
buffer = alloc_buffer_create (result->name, sizeof (result->name));
alloc_buffer_copy_bytes (&buffer, SHMDIR, strlen (SHMDIR));
#if defined (SHM_ANON) && defined (O_TMPFILE)
if (name == SHM_ANON)
{
/* For SHM_ANON, we want shm_open () to pass O_TMPFILE to open (),
with SHMDIR itself as the path. So, leave it at that. */
alloc_buffer_add_byte (&buffer, 0);
if (alloc_buffer_has_failed (&buffer))
return -1;
return 0;
}
#endif
while (name[0] == '/')
++name;
namelen = strlen (name);
if (sem_prefix)
alloc_buffer_copy_bytes (&buffer, "sem.", strlen ("sem."));
alloc_buffer_copy_bytes (&buffer, name, namelen + 1);
if (namelen == 0 || memchr (name, '/', namelen) != NULL)
return EINVAL;
if (alloc_buffer_has_failed (&buffer))
{
if (namelen > NAME_MAX)
return ENAMETOOLONG;
return EINVAL;
}
return 0;
}
Note this code:
while (name[0] == '/')
++name;
The code skips over all leading /
characters if they exist. If there are no leading /
characters, GLIBC proceeds without error.
GLIBC's implementation makes leading /
characters use irrelevant. The result is the same no matter how many leading /
characters are used, even if that number is zero, despite what the sem_overview
man page states.