REALFREE
REALFREE

Reputation: 4396

C: semphore in MAC OS X unexpected sem_close error

I'm trying to use semphore on my mac, and it throws me an error when I try to close an open semaphore. All initializations were successful, but when it attempted to close second semaphore, it returned bad file descriptor error.

Below code is wrapper for open and close:

void init_sem(sem_t * s, char * sema_name, int value)
{
    if((s = sem_open(sema_name, O_CREAT, 0644, value)) == SEM_FAILED)
    {
        perror("sem_open");
        exit(1);
    }
    printf("init semaphore %s\n", sema_name);
}
void destroy_sem(sem_t * s, char * sema_name)
{
    printf("destroying, %s\n", sema_name);
    if (sem_close(s) == -1) {
        perror("sem_close");
        exit(EXIT_FAILURE);
    }

    if (sem_unlink(sema_name) == -1) {
        perror("sem_unlink");
        exit(EXIT_FAILURE);
    }
}

and in main.c

sem_t * s, *a, *b;
init_sem(s, "/cs", 0);
init_sem(a, "/ps", 0);
init_sem(b, "/bs", 0);
destroy_sem(s, "/cs");
destroy_sem(a, "/ps"); //got error here
destroy_sem(b, "/bs");

Any idea why it doesn't work?

Upvotes: 0

Views: 773

Answers (2)

mikhail
mikhail

Reputation: 5179

Gabe's answer is correct.

As an alternative, you can do this:

void init_sem(sem_t ** s, char * sema_name, int value)
{
    if((*s = sem_open(sema_name, O_CREAT, 0644, value)) == SEM_FAILED)
    {
        perror("sem_open");
        exit(1);
    }
    printf("init semaphore %s\n", sema_name);
}
void destroy_sem(sem_t * s, char * sema_name)
{
    printf("destroying, %s\n", sema_name);
    if (sem_close(s) == -1) {
        perror("sem_close");
        exit(EXIT_FAILURE);
    }

    if (sem_unlink(sema_name) == -1) {
        perror("sem_unlink");
        exit(EXIT_FAILURE);
    }
}
int main (int argc, const char * argv[])
{
    sem_t * s, *a, *b;
    init_sem(&s, "/cs", 0);
    init_sem(&a, "/ps", 0);
    init_sem(&b, "/bs", 0);
    destroy_sem(s, "/cs");
    destroy_sem(a, "/ps");
    destroy_sem(b, "/bs");
}

Upvotes: 0

Gabe
Gabe

Reputation: 86718

You are passing in *s where it becomes a local variable. When you assign a value to it, the value goes away when init_sem returns. Then when you call destroy_sim, you are passing in an uninitialized value to sem_close.

You need to return the value that gets returned from sem_open:

sem_t * init_sem(char * sema_name, int value)
{
    sem_t * s;
    if((s = sem_open(sema_name, O_CREAT, 0644, value)) == SEM_FAILED)
    {
        perror("sem_open");
        exit(1);
    }
    printf("init semaphore %s\n", sema_name);
    return s;
}

Then call it like this:

s = init_sem("/cs", 0);
a = init_sem("/ps", 0);
b = init_sem("/bs", 0);

Upvotes: 1

Related Questions