Home > Enterprise >  Semaphores and shared memory already opened / Problem with O_EXCL flag
Semaphores and shared memory already opened / Problem with O_EXCL flag

Time:11-13

I'm currently working on a programm that has a shared memory and semaphores. However I have issues with initializing them. Whenever I wanna open them (whilst having the O_EXCL flag active I keep getting erros. That should mean they are already open when starting but I have no idea how or why.

static sem_t *s1 = NULL;

void initSEM(void)
{
    atexit(closeSEM);
    s1 = sem_open(SEM_1, O_CREAT | O_EXCL, 0600, 1);
    if (s1 == SEM_FAILED)
    {
        printf("%s", "ERROR: Semaphore 1 could not be opened.");
        exit(EXIT_FAILURE);
    }
}

void closeSEM(void)
{
    if (sem_close(s1) == -1)
    {
        exit(EXIT_FAILURE);
    }
    if (sem_close(s2) == -1)
    {
        exit(EXIT_FAILURE);
    }
    if (sem_close(s3) == -1)
    {
        exit(EXIT_FAILURE);
    }
    if (sem_unlink(SEM_1) == -1)
    {
        exit(EXIT_FAILURE);
    }
    if (sem_unlink(SEM_2) == -1)
    {
        exit(EXIT_FAILURE);
    }
    if (sem_unlink(SEM_2) == -1)
    {
        exit(EXIT_FAILURE);
    }
}

In my main function I just call this. Same thing for the shared memory. I have no idea why this is happening.

CodePudding user response:

Your code, as written, need fail to open a single semaphore only once, and from then on, will never properly sem_unlink any of the semaphores, so they continue existing for the next program run.

The sequence of events is:

  1. At some point in development, a sem_open fails for whatever reason
  2. The corresponding sem_close then fails, and you exit(EXIT_FAILURE); rather than performing any remaining sem_close calls and all of the sem_unlink calls, so the named semaphore continues to exist
  3. On future runs, all sem_open calls with O_CREAT/O_EXCL fail (because none of them were unlinked), and the problem is never fixed

The simplest solution is to just remove all the exit(EXIT_FAILURE); calls (perhaps replacing them with debug logging); if the program otherwise ran to completion successfully, cleanup failures aren't that important; it's more important to ensure all the cleanup is performed than to fail-fast when some cleanup fails.

It might also make sense to register separate atexit handlers for each named semaphore, and only after sem_open succeeds for that semaphore, so opening one semaphore doesn't register cleanup functions for all of them, nor does a failed open cause you to schedule cleanup. Doing so would reduce the number of failures expected in common failure cases by limiting cleanup to those cases where it is needed.

  • Related