2012-03-02 2 views
0

J'essaie de synchroniser un père et des enfants, le code suivant ne fonctionne pas (apparemment usr_interrupt ++ n'est pas atomique). Les sémaphores ne semblent pas aider non plus.Impasse avec sigsuspend()

#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; 
} 

Quelqu'un peut-il suggérer une solution? (Je ne peux pas utiliser les threads) Best, - Liron

+0

Réécrivez le code à l'aide des verrouillages automatiques. – AlexTheo

Répondre

1

You can't count signals. Deux signaux du même type a la même signification sémantique comme un signal de ce type. Vous pouvez utiliser deux types de signaux différents, tels que USR1 et USR2. Mais honnêtement, vous ne devriez pas utiliser les signaux comme un mécanisme de communication. Utilisez quelque chose de sensible comme un tuyau.

+0

Merci David. Mais que faire si l'enfant est dans un processus différent? (par exemple I fork et exec)? En outre, j'ai partagé la mémoire pour les processus de communication, donc je veux seulement quelque chose à la synchronisation. –

+0

Utilisez un sémaphore ensuite. Ou utilisez un tuyau nommé. Ou des douilles. –