Home > OS >  How to unlink/close an array of named semaphores in C
How to unlink/close an array of named semaphores in C

Time:12-20

I am trying to create an array of N named POSIX semaphores in C. But I am having trouble unlinking and closing them. I need to use an array of semaphores because each semaphore will represent a segment of a text file that will later go into shared memory.

I am doing something very similar to this post but it is not working. Maybe the problem is in the creation of the semaphores? Is there another way I could do this?

sem_t* semaphores[N];

for(int i = 0; i < N; i  ){
    char buf[100];
    sprintf(buf, "s%d", i);       // Give a unique name to each semaphore
    semaphores[i] = sem_open(buf, O_CREAT | O_EXCL, SEM_PERMS, INITIAL_VALUE);
}

for(int i = 0; i < N; i  ){
    if(sem_unlink((void*)semaphores[i]) < 0){
        perror("sem_unlink(0) failed OVER HERE");
        exit(EXIT_FAILURE);
    }
 }

for(int i = 0; i < N; i  ){
    if(sem_close(semaphores[i]) < 0){
        perror("sem_close(0) failed HERE");
        exit(EXIT_FAILURE);
    }
 }

The error message I am getting is:

sem_unlink(0) failed OVER HERE: No such file or directory

CodePudding user response:

While sem_close(3) takes a sem_t * argument, sem_unlink(3) takes the name of the semaphore as a const char *.

Retain the names of your semaphores, so that they may be passed to sem_unlink(3) later. The example below uses an array of structures to do so.

Additionally, per sem_overview(7), semaphore names should begin with a leading /.

#include <fcntl.h>
#include <semaphore.h>
#include <stdio.h>

#define INITIAL_VALUE 1
#define N 8
#define SEM_PERMS 0666

int main(void)
{
    struct {
        char name[128];
        sem_t *sem;
    } semaphores[N];

    for (size_t i = 0; i < N; i  ) {
        sprintf(semaphores[i].name, "/a-semaphore%zu", i);
        semaphores[i].sem = sem_open(semaphores[i].name,
                O_CREAT | O_EXCL, SEM_PERMS, INITIAL_VALUE);

        if (SEM_FAILED == semaphores[i].sem)
            perror(semaphores[i].name);
    }

    for (size_t i = 0; i < N; i  )
        if (sem_unlink(semaphores[i].name) < 0)
            perror(semaphores[i].name);

    for (size_t i = 0; i < N; i  )
        if (sem_close(semaphores[i].sem) < 0)
            perror(semaphores[i].name);
}

As John points out below, storing each name is not necessarily required. Since the names are algorithmically generated, you could regenerate them from the same template when they are needed again.

A cursory example:

#include <fcntl.h>
#include <semaphore.h>
#include <stdio.h>

#define INITIAL_VALUE 1
#define N 8
#define SEM_PERMS 0666

void namegen(char *dst, size_t suffix)
{
    sprintf(dst, "/a-semaphore%zu", suffix);
}

int main(void)
{
    sem_t *semaphores[N];

    for (size_t i = 0; i < N; i  ) {
        char name[128];
        namegen(name, i);

        semaphores[i] = sem_open(name,
                O_CREAT | O_EXCL, SEM_PERMS, INITIAL_VALUE);

        if (SEM_FAILED == semaphores[i])
            perror(name);
    }

    for (size_t i = 0; i < N; i  ) {
        char name[128];
        namegen(name, i);

        if (sem_unlink(name) < 0)
            perror(name);

        if (sem_close(semaphores[i]) < 0)
            perror(name);
    }
}
  • Related