Thread: Need help with posix semaphores.

  1. #1
    Registered User
    Join Date
    Nov 2010
    Posts
    7

    Need help with posix semaphores.

    Hello, I have this assignment where we need to use semaphores to avoid risk conditions. I understand the concept, but I still cannot get my program to work. Basically, the idea is to have a process create a region of shared memory, and then fork a child. The child is to wait (using semaphores) for the parent to write 2 integers to the region of shared memory. Once the parent writes the 2 integers, the parent is supposed to wait (using semaphores) for the child to read the memory and multiply the 2 numbers in the shared memory. The child should then release the semaphore on the shared memory and the parent should print out the product of the two numbers. The program takes in 2 integers as command line arguments, which are the two integers the parent writes to shared memory.

    Here is my code:
    Code:
    // partA.h
    #include <stdio.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <string.h>
    #include <semaphore.h>
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/shm.h>
    #include <sys/wait.h>
    #include <unistd.h>
    
    #define PROJECT_PATH "Makefile"
    #define PROJECT_ID 'X'
    
    typedef struct info {
      int int1;
      int int2;
      sem_t sem1;
      sem_t sem2;
    } info;
    Code:
    // partA.c
    #include "partA.h"
    
    int main(int argc, char** argv) {
      key_t shm_key;
      int shm_id;
      int int1;
      int int2;
      int err;
      info i;
      info* shm_addr;
      pid_t pid1;
    
      if (argc != 3) {
        printf("Wrong number of arguments.\n");
        exit(1);
      }
    
      // Setup shared memory.
      do {
        shm_key = ftok(PROJECT_PATH, PROJECT_ID);
      } while (shm_key == -1);
    
      do {
        shm_id = shmget(shm_key, sizeof(info), 0644 | IPC_CREAT); 
      } while (shm_id == -1);
    
      do {
        shm_addr = (info*) shmat(shm_id, NULL, 0);
      } while ((void*) shm_addr == (void*) -1);
    
      // Create the semaphores.
      do {
        err = sem_init(&i.sem1, 0, 0);
      } while (err == -1);
    
      do {
        err = sem_init(&i.sem2, 0, 0);
      } while (err == -1);
    
      memcpy(shm_addr, &i, sizeof(info));
      
      // Fork the child.
      pid1 = fork();
    
      if (pid1 == -1) {
        printf("Error forking.\n");
        exit(1);
      } else if (pid1 != 0) {
        int1 = atoi(argv[1]);
        int2 = atoi(argv[2]);
    
        shm_addr->int1 = int1;
        shm_addr->int2 = int2;
    
        // Notify the child that the parent has written to shared memory.
        sem_post(&shm_addr->sem1);
    
        // Wait for the child to compute the product.
        sem_wait(&shm_addr->sem2);
    
        // Print out the product.
        printf("%d\n", shm_addr->int1);
    
        // Delete the shared memory segment.
        if (shmctl(shm_id, IPC_RMID, NULL) == -1)
          printf("Could not delete shared memory.\n");
    
      } else if (pid1 == 0) {    
        // Wait for the parent to finish writing to the shared memory.
        sem_wait(&shm_addr->sem1);
    
        // Compute the product.
        shm_addr->int1 = shm_addr->int1 * shm_addr->int2;
    
        // Notify the parent that the product has been computer.
        sem_post(&shm_addr->sem2);
      }
    
      return 0;
    }
    I'm sorry to post so much code, but I think I am having some type of syntax error somewhere. The code compiles, but it deadlocks and never prints out the answer. Using print statements, I was able to determine that the code of the child executes, but the parent is never woken up. Any help would be greatly appreciated. Oh, and the semaphores are initialized to 0, so I don't think it matters that I didn't wait on the semaphore in the parent.

  2. #2
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    Don't put your error checking in a do/while - you'll most likely just be in an infinite loop if an error occurs. Use an "if" to detect the error condition and call perror() followed by exit().
    http://www.opengroup.org/onlinepubs/...ns/perror.html

    Since only forked processes access the shared memory, "IPC_PRIVATE" could be used in the first parameter to shmget() instead of calling ftok().

    >> memcpy(shm_addr, &i, sizeof(info));
    A "sem_t" is not copyable. Behavior is undefined if a copy is used. Remove "i" and use "shm_addr" directly.

    The second parameter to sem_init() should be non-zero - since multiple processes will be using them.
    http://www.opengroup.org/onlinepubs/.../sem_init.html

    gg

  3. #3
    Registered User
    Join Date
    Nov 2010
    Posts
    7
    Thanks coedplug. Changing pshared from 0 to 1 fixed the problem. I had actually read the page you posted and read about setting pshared, I just had a momentary lapse in reason and misunderstood what it meant to be 0 or nonzero. I also didn't know about IPC_PRIVATE which is pretty cool. I removed the memcpy too, which was something I had only added because I was desperately trying to find ways to make the program work.

    Thanks for all the help.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Posix threads synchronisation with semaphores
    By evariste in forum C Programming
    Replies: 6
    Last Post: 10-26-2010, 03:41 PM
  2. semaphores
    By Dr Spud in forum C Programming
    Replies: 7
    Last Post: 09-22-2007, 12:45 PM
  3. Problems with POSIX semaphores.
    By Volanin in forum Linux Programming
    Replies: 2
    Last Post: 07-13-2007, 02:32 PM
  4. Problem with POSIX semaphores
    By kaseo88 in forum C Programming
    Replies: 7
    Last Post: 06-29-2007, 12:31 PM
  5. Semaphores Problems
    By mhelal in forum Linux Programming
    Replies: 2
    Last Post: 05-06-2007, 10:36 PM