Liron Cohen
Liron Cohen

Reputation: 65

Deadlock with sigsuspend()

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

Upvotes: 0

Views: 585

Answers (1)

David Schwartz
David Schwartz

Reputation: 182779

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.

Upvotes: 1

Related Questions