Tom
Tom

Reputation: 332

Semaphore value initialized to -1?

I am trying to initialize a binary semaphore for some shared memory. I could not figure out why I hung on a semop to get the semaphore, and eventually found that the semaphore value was -1 and I was stuck waiting. What I don't get is why the semaphore value is initializing to -1 to begin with. Any help clarifying this would be greatly appreciated.

semID = semget(IPC_PRIVATE, 1, S_IRUSR | S_IWUSR); // create sem
int semval = semctl(semID, 1,GETVAL);

printf("After init Semaphore value = %d \n", semval);
printf("sem ID = %d \n", semID);

Output :

 After init semaphore value = -1 
 sem ID = 524304 

Upvotes: 1

Views: 1522

Answers (2)

zwol
zwol

Reputation: 140579

You have two bugs. Your first bug is that, as always in C, the array of semaphores created by semget is 0-indexed; so, if you create only one semaphore, the second argument to semctl with that semid should be 0, not 1. The -1 you're getting back from semctl is not the value of the semaphore, but an error indication (you should find that errno == EINVAL).

Your second bug is more subtle. The POSIX.1-2008 specification for semget says:

Upon creation, ...

  • the data structure associated with each semaphore in the set need not be initialized. The semctl() function with the command SETVAL or SETALL can be used to initialize each semaphore.

(emphasis mine) What that means is, your code cannot rely on a new SysV semaphore having any specific value when it's first created. You have to do something like this:

semID = semget(IPC_PRIVATE, 1, S_IRUSR|S_IWUSR);
if (semID < 0) {
    perror("semget");
    return -1;
}

union semun arg;
arg.val = 0;
if (semctl(semID, 0, SETVAL, arg) == -1) {
    perror("semctl");
    return -1;
}

// only now is it safe to use the semaphore

Note that you have to copy the definition of union semun out of the documentation into your code; it is not provided by any header.

If you're starting to get the feeling that this API is terrible, you are 100% correct. You may find the semaphore.h API more congenial, however it is less widespread.

Upvotes: 4

Brian Sidebotham
Brian Sidebotham

Reputation: 1906

Actually, the man page for semctl tells you that a return value of -1 means there was an error.

To get the error use strerror printf( "%s", strerror(errno) );

Don't forget #include <errno.h> and #include <string.h>

Upvotes: 2

Related Questions