1

I'm implementing a solution to a problem that uses shared memory, but somehow, my code seems to "freeze" between a print statement and an if statement.

Here's the relevant code snippet:

#include "ch_problem_headers.h"
int main(int argc, char *argv[])
{
  int semid, shmid;
  int i;
  int waiting_C, waiting_H = 0; // shared
  int c_pid,h_pid;
  time_t t;
  // There should be three semaphores: S for when to pass the molecule on,
  // SC for the carbon waiting, and SH for the hydrogen waitin

  unsigned short seminit[NUM_SEMS];
  struct common *shared;
  union semun semctlarg;

  srand((unsigned)time(&t));

  if((semid = semget(IPC_PRIVATE, NUM_SEMS, IPC_CREAT|0777)) < 0)
  {
    perror("semget");
    exit(EXIT_FAILURE);
  }

  // Initialize semaphores
  seminit[S_SEM] = 1;
  seminit[SC_SEM] = 0;
  seminit[SH_SEM] = 0;
  semctlarg.array = seminit;

  // Apply initialization
  if((semctl(semid, NUM_SEMS, SETALL, semctlarg)) < 0)
  {
    perror("semctl");
    exit(EXIT_FAILURE);
  }

  // Get shared memory id
  if((shmid = shmget(IPC_PRIVATE, 1*K, IPC_CREAT|IPC_EXCL|0660)) < 0)
  {
    perror("shmget");
    exit(EXIT_FAILURE);
  }

  // Retrieve pointer to shared data structure
  if((shared = (struct common *)shmat(shmid, 0, 0)) < 0)
  {
    perror("shmat");
    exit(EXIT_FAILURE);
  }

  shared->waiting_C = 0;
  shared->waiting_H = 0;

  printf("ready to fork\n");
  // fork process C
  c_pid = fork();
  printf("c_pid is %d\n", c_pid);
  if(c_pid == 0)
  {
    printf("I'm process C!/n");
    // wait on S
    semWait(semid, S_SEM);
    // if waiting_H >= 4
    if(shared->waiting_H >= 4)
    {
      //    signal SH four times
      for(i = 0; i < 4; i++)
      {
        semSignal(semid, SH_SEM);
        printf("H");
      }
      //    Decrement waiting_H by 4
      shared->waiting_H -= 4;
      //    Signal S
      semSignal(semid, S_SEM);
    }
    // Otherwise, increment waiting_C by 1
    else
    {
      shared->waiting_C += 1;
      //      Signal S and wait for SC
      semSignal(semid, S_SEM);
      semWait(semid, SC_SEM);
    }
  }
  else
  {
    printf("C's process id is %d\n", c_pid);

    printf("ready to fork again\n");
    // fork process H
    h_pid = fork();
    printf("Is h_pid zero? %d\n", (h_pid == 0));
    if(h_pid == 0)
    {
      printf("I'm process H!/n");
      // Wait on S
      semWait(semid, S_SEM);
      // If waiting_h >= 3
      if(shared->waiting_H >= 3)
      {
        //   Signal SH three times, decrement waiting_H by 3, signal SC, decrement
        for(i = 0; i < 3; i++)
        {
          printf("H");
          semSignal(semid, SH_SEM);
        }
        shared->waiting_H -=3;
        semSignal(semid, SC_SEM);
        shared->waiting_C -= 1;
        semSignal(semid, S_SEM);
        //   waitng_C by 1, and signal S
      }
      // Otherwise, increment waiting_H by 1, signal S, and wait on SH
      else
      {
        shared->waiting_H += 1;
        semSignal(semid, S_SEM);
        semWait(semid, SH_SEM);
      }
    }
    else
    {
      printf("In the parent\n");
    }
  }
}

And the relevant header file:

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/errno.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>

#define K 1024

#define NUM_SEMS 3
#define SEMKEY 77
#define SHMKEY 77

#define S_SEM 0
#define SH_SEM 1
#define SC_SEM 2

#define NUM_H 4
#define NUM_C 1

union semun
{
  unsigned short *array;
};

struct common
{
  int waiting_C;
  int waiting_H;
};

void semWait(int semid, int semaphore)
{
  struct sembuf psembuf;

  psembuf.sem_op = -1;
  psembuf.sem_flg = 0;
  psembuf.sem_num = semaphore;
  semop(semid, &psembuf, 1);
  return;
}

void semSignal(int semid, int semaphore)
{
  struct sembuf vsembuf;

  vsembuf.sem_op = 1;
  vsembuf.sem_flg = 0;
  vsembuf.sem_num = semaphore;
  semop(semid, &vsembuf, 1);
  return;
}

The program output when run is as follows:

Parent output (correct) :

ready to fork

c_pid is 2977

C's process ID is 2977

ready to fork again

Is h_pid zero? 0

In the parent

Child output:

Is h_pid zero? 1

c_pid is 0

I tried running the program in valgrind, and the program simply halted after the child output. I'm confused as to how this is possible, as the program seems to simply stop between the c_pid print statement and the if(c_pid == 0) statement.

Does anyone have any idea why this might be? Thanks so much.

jdarthenay
  • 3,062
  • 1
  • 15
  • 20
Haley
  • 77
  • 1
  • 12
  • Why did you remove the C tag? This is C code, C tag is relevant. – jdarthenay Mar 27 '16 at 06:34
  • @jdarthenay Must have accidentally removed it while editing the parenthesis. Thanks for pointing that out. – Haley Mar 27 '16 at 06:50
  • Also, big thanks for taking another look at my formatting, @jdarthenay. Didn't catch it all during my first edit. – Haley Mar 27 '16 at 06:57
  • Typo: `printf("I'm process C!/n");` should be `printf("I'm process C!\n");`. That explains why that print statement doesn't show - `printf` is line buffered and will not flush to stdout until a newline is encountered. – kaylum Mar 27 '16 at 06:57
  • @kaylum Thank you! Amazingly, that typo had me held up for hours. Big thanks again! – Haley Mar 27 '16 at 07:01
  • According to `srand()` and `rand()`man page, you should not use these functions but `srandom()`and `random()`. http://linux.die.net/man/3/srand – jdarthenay Mar 27 '16 at 07:01
  • @jdarthenay Good catch. Another thanks to you! – Haley Mar 27 '16 at 07:03
  • 1
    What happens when you step through with a debugger attached? – David Hoelzer Mar 27 '16 at 07:07
  • @DavidHoelzer To be perfectly honest, I don't know how to do that on command-line Linux. I've been using valgrind this whole time. Any suggestions? – Haley Mar 27 '16 at 07:21
  • 1
    Do some reading on `gdb`. – David Hoelzer Mar 27 '16 at 07:37
  • What @DavidHoelzer says. SO is NOT a free debugging service for you to abuse as you see fit. If you cannot use a debugger in your environment, you shoud not be developing software on it as you are mssing a basic skill. – Martin James Mar 27 '16 at 08:14
  • @MartinJames I doubt most students coming to SO have been shown how to use GDB, I bet some are not even aware of it's existence. – Harry Mar 27 '16 at 08:44
  • @Harry yes, I am aware of the gross incompetence of some teaching staff:( – Martin James Mar 27 '16 at 13:00
  • @MartinJames I apologize for my ignorance. I thought valgrind was the only software available for command-line Linux, as that is what my teacher has told us to use. This environment is required for a course. Harry was right: I have never been shown how to use 'gdb', nor did I know it existed until David pointed it out. I am new to this community. I never took SO as a free debugging service, and I thought this question was appropriate to post. I apologize if I was incorrect. Please don't tell me or anyone else who makes a simple mistake that they "shouldn't be developing." – Haley Mar 27 '16 at 18:42
  • @DavidHoelzer I did some reading on gdb and it's been very useful. Thank you for your suggestion! – Haley Mar 27 '16 at 19:32
  • @Haley NO! It's not your ignorance that is the issue, it's poor organization of the curriculum and teaching failures. Nevertheless, I stand by my statement/s: 'OK, you can operate your car well and get it from A to B safely, but since you just stop at roundabouts and are unable to proceed without someone else manouvering your car to the other side of the junction, you should not drive since you are wasting everyone's time'. – Martin James Mar 27 '16 at 22:07
  • Your prof/TA should be ensuring that you do not just stop at roundabouts, unable to progress without help. – Martin James Mar 27 '16 at 22:08
  • Amazing that they would tell you about valgrind but not gdb or lldb! Welcome to the tools of real programmers. :) – David Hoelzer Mar 27 '16 at 23:42
  • Thanks for clarifying, @MartinJames. I appreciate it very much. He's a new teacher and also a grad student, but I agree with you and want to make that point to him in class on Monday. Hopefully this can help not just me, but all his future students learn to be self-sufficient C programmers :) – Haley Mar 28 '16 at 06:01
  • Thanks, @DavidHoelzer! Glad to be here. :) – Haley Mar 28 '16 at 06:02

0 Answers0