How to reliably initialize IPC semaphores?

690 views Asked by At

The problem: How to use SysV semaphores for synchronisation between two processes (let’s call them procA and procB), assuming that both are independently run from the shell (none of them is spawned by the fork/exec combination) and that the semaphores must be created by one of these two processes.

Quoting man semget:

The values of the semaphores in a newly created set are indeterminate. (POSIX.1-2001 is explicit on this point.) Although Linux, like many other implementations, initializes the semaphore values to 0, a portable application cannot rely on this: it should explicitly initialize the semaphores to the desired values.

Assume we would like to write portable code that relies only on POSIX guarantees, but no Linux-specific guarantees. Very well, so it is impossible to atomically create a semaphore set and initialize it. This must be done by two separate calls.

So, the code for creation of the semaphore set for procA would look sth like this:

int sem_id = semget(key, nsems, IPC_CREAT | S_IRWXU);

And same for procB – this way, whichever process happens to need the semaphores for the first time, it also creates them; otherwise, it simply obtains the semaphore set’s ID and is ready to use it.

Problems start to appear when initialisation is required. The instruction for initialisation is of course semctl with SETALL – but: • the initialisation should be done only once, and • the initialisation should be done before the semaphores are used. This could of course be enforced by… semaphores, but such such solution is unfortunately recursive: we need semaphores to set up semaphores, which themselves need semaphores to be set up and so forth.

Is it possible to do this only using sysV semaphores, or am I right in my assumption that I have to resort to other IPC facilities like signals or message queues to be able to reliably set up these semaphores?

1

There are 1 answers

0
dan4thewin On

In my experience this isn't a problem in the real world. I put the IPC creation and initialization in a separate program that is called by a system startup script in advance of any client program being run. The IPC resources are never removed, and only go away when the box is rebooted.

If I had to create the resources on the fly, I'd have the creator program start as a separate user and create the resource with owner-only permissions. It would then initialize it, and finally grant permissions to the client's user, and exit.

The clients would simply retry on ENOENT or EACCES, perhaps with a nanosleep.

On second though, I'd probably just use POSIX semaphores, since sem_open(3) let's you specify O_EXCL and an initial value. Old Sys V habits are hard to break.