Linus
Linus

Reputation: 1123

How to prevent errors when destroying semaphores in C on linux?

I'm making a small assignment using semaphores. I want to destroy the semaphore once the program is finished, but every time I try to it gives me an error: "Invalid argument". I've followed several examples that DO work, but I can't see what I'm doing differently. Here's my code:

#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

void display(char *str) {
  char *tmp;
  for (tmp=str;*tmp;tmp++) {
    write(1,tmp,1);
    usleep(100);
  }
}

int main() {
  struct sembuf up = {0,1,0};
  struct sembuf down = {0,-1,0};
  int i, my_sem;

  my_sem = semget(IPC_PRIVATE, 1, 0600); /*create semaphore*/
  if(my_sem<0){
    perror("Error getting semaphore:");
  }

  if(semop(my_sem, &up, 1)){perror("error changing semaphore:");}; /*set to 1*/

  if (fork()) {
    for (i=0;i<10;i++) {
      if(semop(my_sem, &down, 1)){perror("error changing semaphore:");}; 
      display("Hello world\n");
      if(semop(my_sem, &up, 1)){perror("error changing semaphore:");}; 
    }
    wait(NULL);
  }
  else {
    for (i=0;i<10;i++) {
      if(semop(my_sem, &down, 1)){perror("error changing semaphore:");};
      display("Bonjour monde\n");
      if(semop(my_sem, &up, 1)){perror("error changing semaphore:");}; 
    }
  }

  if(semctl(my_sem,0,IPC_RMID)){perror("error destroying semaphore:");}  /*destroy the semaphore*/

  return 0;
}

This results in the following output:

Hello world
Bonjour monde
Hello world
Bonjour monde
Hello world
Bonjour monde
Hello world
Bonjour monde
Hello world
Bonjour monde
Hello world
Bonjour monde
Hello world
Bonjour monde
Hello world
Bonjour monde
Hello world
Bonjour monde
Hello world
Bonjour monde
error destroying semaphore:: Invalid argument

Who can tell me why?!

Thanks!

Linus

Upvotes: 1

Views: 481

Answers (1)

Karl Bielefeldt
Karl Bielefeldt

Reputation: 49078

It's because you are destroying it in both threads. The second attempt fails. Put that statement inside the if block after the wait.

Upvotes: 2

Related Questions