0

I am trying to synchronize a father and children, the following code is not working (apparently usr_interrupt++ is not atomic). Semaphores does not seems to help either.

#include <sys/types.h>
#include <sys/ipc.h> 
#include <sys/shm.h> 
#include <sys/stat.h>
#include <unistd.h>
#include <cstdlib>
#include <iostream>
#include <unistd.h>
#include <cstring>
#include <string>
#include <semaphore.h>
#include <fcntl.h>

using namespace std;

/* When a SIGUSR1 signal arrives, set this variable.   */
volatile sig_atomic_t usr_interrupt;
sem_t *mutex;
char* SEM_NAME;

void 
synch_signal (int sig)
{
  // sem_wait(mutex);
  usr_interrupt++;
  // sem_post(mutex);
}

/* The child process executes this function.  */
void 
child_function (void)
{

  /* Perform initialization.  */
  cerr << "I'm here!!!  My pid is " << (int)getpid() << " my usr_int=" << usr_interrupt << endl;
  /* Let parent know you're done.  */
  kill (getppid (), SIGUSR1);
  /* Continue with execution.  */
  cerr << "Bye, now...." << endl;
  exit(0);
}

int
main (void)
{
  usr_interrupt = 0;

  string s_sem_name = "lir";
  SEM_NAME = new char[s_sem_name.size()+1];
  memcpy(SEM_NAME, s_sem_name.c_str(), s_sem_name.size());
  SEM_NAME[s_sem_name.size()] = '\0';
  mutex = sem_open (SEM_NAME,O_CREAT,0644,1);
  if(mutex == SEM_FAILED) {
    perror("unable to create semaphore");
    sem_unlink(SEM_NAME);
    exit(-1);
  }


  struct sigaction usr_action;
  sigset_t mask, oldmask;
  pid_t child_id, child_id2;

  /* Set up the mask of signals to temporarily block. */ 
  sigemptyset (&mask); 
  sigaddset (&mask, SIGUSR1);

  /* Establish the signal handler.*/
  usr_action.sa_handler = synch_signal;
  usr_action.sa_flags = 0;
  sigaction (SIGUSR1, &usr_action, NULL);

  /* Create the 2 children processes.  */
  child_id = fork ();
  if (child_id == 0)
    child_function ();

  child_id2 = fork();
  if (child_id2 == 0)
    child_function ();

  /* Wait for a signal to arrive. */
  sigprocmask (SIG_BLOCK, &mask, &oldmask);
  while (usr_interrupt != 2) {
    sigsuspend (&oldmask);
  }
  sigprocmask (SIG_UNBLOCK, &mask, NULL);


  /* Now continue execution.  */
  puts ("That's all, folks!");

  return 0;
}

Can anyone suggest a fix? (I cannot use threads) Best, -- Liron

1 Answers1

1

You can't count signals. Two signals of the same type has the same semantic meaning as one signal of that type. You could use two different signal types like USR1 and USR2. But honestly, you shouldn't use signals as a communication mechanism. Use something sensible like a pipe.

Community
  • 1
  • 1
David Schwartz
  • 179,497
  • 17
  • 214
  • 278
  • Thanks David. But what if the child is in a different process? (e.g. I fork and exec)? Also, I have shared memory for the processes for communication, so I only want something to synchronization. – Liron Cohen Mar 02 '12 at 15:06
  • Use a semaphore then. Or use a named pipe. Or sockets. – David Schwartz Mar 02 '12 at 15:12