How to get return value of sem_wait()?

I have a program that's supposed to let two processes alternate between doing a certain task. After the fifth time the child process executes its task it has to destroy a semaphore and the parent process is supposed to stop because of it.

This sounded fairly easy at first, but I'm having difficulty capturing the return value of the sem_wait() function.

Here's my file:

#include "Part2Defs.h"

int main() {

  FILE *fptr = 0;

  sem_t *child  = mmap(0, sizeof(sem_t), PROT_READ|PROT_WRITE,
                       MAP_SHARED|MAP_ANONYMOUS, -1, 0);

  sem_t *parent = mmap(0, sizeof(sem_t), PROT_READ|PROT_WRITE,
                 MAP_SHARED|MAP_ANONYMOUS, -1, 0);

  /* save the number that we'll be writing to the file */
  int number = 1, removed = 0;

  sem_init(child,  1, 1);
  sem_init(parent, 1, 0);


  fptr = fopen(BUFFER, "r+");
  if(fptr == 0) {
    printf("An error occurred while opening the file\n");
  }

  fprintf(fptr, "%d", number);

  fclose(fptr);

  int pID = fork();

  if(pID == 0) {

    /* do this FOREVER. */
    while(1) {

      /* I was hoping to get the return value here */
      if(sem_wait(parent) == 0) {

      /* open the file */
      fptr = fopen(BUFFER, "r+");

      printf("B. The number [] was modified by parent\n");

      fclose(fptr);
      sem_post(child);
      }
      else {
        printf("--parent-- waiting for new number to be READ: Identifier removed");
      }
    } 

    return 0;
  }
  else if(pID > 0) {

    /* make a counter to go from 0 to 5 */
    int i = 0;
    while(1) {

      sem_wait(child);

     if(i++ == 5) {
        /* delete the semaphore */
        sem_destroy(parent);

        printf("Semaphore removed\n");
        break;
      }
       /* open the file */
      fptr = fopen(BUFFER, "r+");

      printf("A. The number [] was modified by child\n");

      fclose(fptr);
      sem_post(parent);
   }

    return 0;
  }
  else {
    printf("There was an error creating the fork.\n");
    exit(1);
  }
}

Here's my output:

A. The number [] was modified by child
B. The number [] was modified by parent
A. The number [] was modified by child
B. The number [] was modified by parent
A. The number [] was modified by child
B. The number [] was modified by parent
A. The number [] was modified by child
B. The number [] was modified by parent
A. The number [] was modified by child
B. The number [] was modified by parent
Semaphore removed

Which is almost exactly what I was hoping for, except the parent process never ended with the message containing the error.

BY THE WAY: this is homework, but I'm supposedly not allowed to add the homework tag on my own post because of my lack of reputation.

Answers


http://man7.org/linux/man-pages/man3/sem_destroy.3.html :

"Destroying a semaphore that other processes or threads are currently blocked on (in sem_wait(3)) produces undefined behavior."

I found a way to use one of the semaphores as a flag to tell the parent when it's done.

#include "Part2Defs.h"


int main() {

  FILE *fptr = 0;

  sem_t *child  = mmap(0, sizeof(sem_t), PROT_READ|PROT_WRITE,
                       MAP_SHARED|MAP_ANONYMOUS, -1, 0);

  sem_t *parent = mmap(0, sizeof(sem_t), PROT_READ|PROT_WRITE,
                 MAP_SHARED|MAP_ANONYMOUS, -1, 0);

  /* save the number that we'll be writing to the file */
  int number = 1, removed = 0;

  sem_init(child,  1, 0);
  sem_init(parent, 1, 0);


  fptr = fopen(BUFFER, "r+");
  if(fptr == 0) {
    printf("An error occurred while opening the file\n");
  }

  fprintf(fptr, "%d", number);

  fclose(fptr);

  int pID = fork();

  if(pID == 0) {

    /* do this FOREVER. */
    while(1) {
      sem_post(child);
      sem_wait(parent);
      if(!sem_trywait(child))
          break;
      /* open the file */
      fptr = fopen(BUFFER, "r+");

      printf("B. The number [] was modified by parent\n");
      fflush(stdout);

      fclose(fptr);
    }

    sem_destroy(child);
    sem_destroy(parent);

    printf("--parent-- waiting for new number to be READ: Identifier removed");
    return 0;
  }
  else if(pID > 0) {

    /* make a counter to go from 0 to 5 */
    int i = 0;
    while(1) {
      sem_wait(child);

     if(i++ == 5) {
        sem_post(child);
        sem_post(parent);
        //Signal the parent that it's done by adding one to child.

        printf("Semaphore removed\n");
        break;
      }
       /* open the file */
      fptr = fopen(BUFFER, "r+");

      printf("A. The number [] was modified by child\n");
      fflush(stdout);

      fclose(fptr);

      sem_post(parent);
   }

    return 0;
  }
  else {
    printf("There was an error creating the fork.\n");
    exit(1);
  }
}

sem_wait's return value only reflects its seccess/failure in acquiring the lock. If you want communication between processes, you need another mechanism (for example, shared memory).


Need Your Help

Speed-up SQL Insert Statements

sql .net sql-server-2008

I am facing an issue with an ever slowing process which runs every hour and inserts around 3-4 million rows daily into an SQL Server 2008 Database.