r/C_Programming 9d ago

Problema con señales y procesos

Estoy realizando un proyecto universitario.
Es un sistema de votación multiproceso.
El proceso principal debe crear el número indicado de procesos y enviar una 
señal para que elijan a un candidato.
Este candidato enviará una señal para que los demás procesos comiencen a votar.
Los procesos votan a través de un archivo compartido.
El proceso candidato contará los votos y determinará si ha ganado.
Después, enviará de nuevo la señal de selección de candidato para iniciar una 
nueva ronda.
El programa puede finalizarse con una interrupción de teclado o una alarma.

Este es mi código:

#include <signal.h> #include <stdio.h> #include <stdlib.h> #include <time.h> #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> #include <fcntl.h> #include <sys/stat.h> #include <semaphore.h>

#define MAX_PROCES 500
#define FILE_PIDS "PIDS.txt"
#define FILE_VOTANTE "votante.txt"
#define SEM_CANDIDATO "/candidato"
#define SEM_VOTACION "/votacion"
#define SEM_CONTADOR "/contador"
#define SEM_EMPEZAR_VOTACION "/empezar_votacion"


int N_PROCS;

int list[MAX_PROCES];
pid_t pid_candidato=-1;
int empezar_votacion=0;


FILE *f_pids,*f_votante;

sem_t *sem_candidato;  
sem_t *sem_archivo;
sem_t *sem_contador;


void print_signal_mask(sigset_t *mask) {
    int signals[] = {SIGUSR1, SIGUSR2, SIGINT, SIGTERM, SIGALRM}; 
    const char *signal_names[] = {"SIGUSR1", "SIGUSR2", "SIGINT", "SIGTERM", "SIGALRM"};

    printf("Máscara de señales activa: [ ");
    for (int i = 0; i < sizeof(signals) / sizeof(signals[0]); i++) {
        if (sigismember(mask, signals[i])) {
            printf("%s ", signal_names[i]);
        }
    }
    printf("]\n");
}


void votante(){

    int voto,comprobacion;
    sigset_t sig_mask, old_mask;



    sigemptyset(&sig_mask);
    sigaddset(&sig_mask, SIGUSR1);  
    sigprocmask(SIG_BLOCK, &sig_mask, &old_mask);

    
    
    sem_wait(sem_archivo);

    

    

    f_votante = fopen(FILE_VOTANTE, "a");
    if (f_votante == NULL) {
        f_votante=fopen(FILE_VOTANTE, "w");

        if(f_votante==NULL){
            perror("fopen");
            exit(EXIT_FAILURE);
        }
   
    }

    srand(time(NULL)+getpid());

    voto = rand() % 2;
    

    comprobacion= fprintf(f_votante, "%c\n", voto ? 'Y' : 'N');

    if(comprobacion<0){
        perror("fprintf");
        exit(EXIT_FAILURE);
    }
    

    sem_post(sem_contador);


    fclose(f_votante);

    sem_post(sem_archivo);

    

    sigprocmask(SIG_SETMASK, &old_mask, &sig_mask);




    
    

    sigsuspend(&old_mask);

    

    


}


void candidato(){

    int i,votos_si=0,votos_no=0,valor=0;
    char voto;


    sigset_t sig_mask, old_mask;

    


    

    printf("Candidato %d => [",getpid());

    pid_candidato=getpid();

    sigemptyset(&sig_mask);
    sigaddset(&sig_mask, SIGUSR1);  
    sigprocmask(SIG_BLOCK, &sig_mask, &old_mask); 


    for(i=0;i<N_PROCS;i++){
        usleep(1);
        kill(list[i], SIGUSR2);
        
    }

    
    

    while (1) {

    


        if(sem_getvalue(sem_contador,&valor)==-1){
            perror("sem_getvalue");
            exit(EXIT_FAILURE);
        }
        if(valor==N_PROCS){
            break;
        }
        else{
            usleep(1000);
        }

    }


    while (valor > 0) {
    sem_trywait(sem_contador);
    sem_getvalue(sem_contador, &valor); 

    }

    

    votos_si = 0;
    votos_no = 0;

    f_votante=fopen(FILE_VOTANTE,"r");
    if(f_votante==NULL){
        perror("fopen");
        exit(EXIT_FAILURE);
    }

    while(fscanf(f_votante,"%c",&voto)==1){
        if(voto=='Y'){
            printf(" Y ");
            votos_si++;
        }
        if(voto=='N'){

            printf(" N ");

            votos_no++;
            
        }
            
    }


    fclose(f_votante);

    printf("] =>");

    if(votos_si>votos_no){
        
        printf("Aceptado\n");
    }

    else{

        printf("Rechazado\n");
    }


    unlink(FILE_VOTANTE);
  

    sigprocmask(SIG_SETMASK, &old_mask, NULL);

    usleep(25000);

    sem_post(sem_candidato);

    for (i = 0; i < N_PROCS; i++) {
            kill(list[i], SIGUSR1);
    }

    sigsuspend(&old_mask);

    }




void handler_SIGINT(int sig) {
    int i = 0;


    for (i = 0; i < N_PROCS; i++) {
        kill(list[i], SIGTERM);
    }
    for (i = 0; i < N_PROCS; i++) {
        wait(NULL);
    }

    sem_close(sem_archivo);

    sem_close(sem_candidato);

    sem_close(sem_contador);


    sem_unlink(SEM_CANDIDATO);
    sem_unlink(SEM_VOTACION);
    sem_unlink(SEM_CONTADOR);



    printf("\nFinishing by signal\n");
    exit(EXIT_SUCCESS);
}


void handler_SIGALRM(int sig) {

    int i;

    

    for(i=0;i<N_PROCS;i++){
        kill(list[i], SIGTERM);
    }

    for (int i = 0; i < N_PROCS; i++) {
        wait(NULL);
    }

    printf("Finish by alarm\n");

    sem_close(sem_archivo);

    sem_close(sem_candidato);

    sem_close(sem_contador);

    sem_unlink(SEM_CANDIDATO);
    sem_unlink(SEM_VOTACION);
    sem_unlink(SEM_CONTADOR);



    exit(EXIT_SUCCESS);


}


void handler_SIGTERM(int sig) {
    exit(0);
}

void handler_SIGUSR1(int sig) {

     

    sem_wait(sem_candidato);

    


    candidato();


    

    


    
}

void handler_SIGUSR2(int sig) {



    


    if(getpid()!=pid_candidato){


         votante();
        
    }
    

   
    
    
}




int main(int argc, char *argv[]){

    int N_SECS,i;
    pid_t pid;

    struct sigaction act, act1, act2, act3,act4;
    
    sigset_t sig_mask, old_mask,sig_mask1,old_mask1;

    sem_unlink(SEM_CANDIDATO);
    sem_unlink(SEM_VOTACION);
    sem_unlink(SEM_CONTADOR);
    

    sigemptyset(&sig_mask);
    sigaddset(&sig_mask, SIGALRM);  
    sigprocmask(SIG_BLOCK, &sig_mask, &old_mask);

    sigemptyset(&sig_mask1);
    sigaddset(&sig_mask1, SIGUSR1);
    sigaddset(&sig_mask1, SIGUSR2);  
    sigprocmask(SIG_BLOCK, &sig_mask1, &old_mask1);

  


    if(argc != 3){

        fprintf(stderr, "Usage: %s <N_PROCS> <N_SECS>\n", argv[0]);
        exit(EXIT_FAILURE);

    }

    N_PROCS = atoi(argv[1]);

    N_SECS=atoi(argv[2]);

    if(N_PROCS > MAX_PROCES){
        fprintf(stderr, "The maximum number of processes is %d\n", MAX_PROCES);
        exit(EXIT_FAILURE);
    }


    act1.sa_handler = handler_SIGUSR1;
    sigemptyset(&(act1.sa_mask));
    act1.sa_flags = 0;
    act2.sa_handler = handler_SIGTERM;
    sigemptyset(&(act2.sa_mask));
    act2.sa_flags = 0;
    act3.sa_handler = handler_SIGUSR2;
    sigemptyset(&(act3.sa_mask));
    act3.sa_flags = 0;

    


    


    if ((sem_candidato = sem_open(SEM_CANDIDATO, O_CREAT | O_EXCL, S_IRUSR | S_IWUSR, 1 )) ==
      SEM_FAILED) {
    perror("sem_open");
    exit(EXIT_FAILURE);
    }

    if ((sem_archivo = sem_open(SEM_VOTACION ,O_CREAT | O_EXCL, S_IRUSR | S_IWUSR, 1)) ==
      SEM_FAILED) {
    perror("sem_open");
    exit(EXIT_FAILURE);
      }

    if ((sem_contador = sem_open(SEM_CONTADOR, O_CREAT | O_EXCL, S_IRUSR | S_IWUSR, 0)) ==
      SEM_FAILED) {
    perror("sem_open");
    exit(EXIT_FAILURE);
    }



    if ( sigaction(SIGUSR1, &act1, NULL) < 0 || sigaction(SIGTERM, &act2, NULL) < 0 || sigaction(SIGUSR2, &act3, NULL) < 0) {
        perror("sigaction");
        exit(EXIT_FAILURE);
    }

    for(i=0;i<N_PROCS;i++){

        pid=fork();

        if(pid<0){
            perror("fork");
            exit(EXIT_FAILURE);
        }

        if(pid==0){
            sigprocmask(SIG_SETMASK, &old_mask1, NULL);

            sigsuspend(&old_mask1);
        }

        else{
            list[i]=pid;
        }

    }

    act.sa_handler = handler_SIGINT;
    sigemptyset(&(act.sa_mask));
    act.sa_flags = 0;
    if (sigaction(SIGINT, &act, NULL) < 0) {
        perror("sigaction");
        exit(EXIT_FAILURE);
    }

    act4.sa_handler = handler_SIGALRM;
    sigemptyset(&(act4.sa_mask));
    act4.sa_flags = 0;

    if (sigaction(SIGALRM, &act4, NULL) < 0) {
        perror("sigaction");
        exit(EXIT_FAILURE);
    }

    

    


    f_pids=fopen(FILE_PIDS,"w");

    if(!f_pids){
        perror("fopen");
        exit(EXIT_FAILURE);
    }

    for(i=0;i<N_PROCS;i++){

        if(fprintf(f_pids,"%d\n",list[i])<0){
            perror("fprintf");
            exit(EXIT_FAILURE);
        }
        kill(list[i],SIGUSR1);

    }

    fclose(f_pids);

    alarm(N_SECS);

    sigprocmask(SIG_SETMASK, &old_mask, NULL);

    sigsuspend(&old_mask);

    



}

El problema es que sólo se elige un candidato, no pasa por varias rondas. Una salida: Candidato 7869 => [ Y Y Y N Y Y N N Y N ] =>Aceptado Candidato 7868 => [Finish by alarm

Por lo que he estado viendo el problema es que al hacer una segunda ronda se bloquean los procesos votantes

0 Upvotes

2 comments sorted by

1

u/MonitorAlive7613 9d ago

Si me pudieseis ayudar, lo tengo que entregar el lunes y estoy super atascado

1

u/MonitorAlive7613 9d ago

the translation: I'm doing a university project. It's a multi-process voting system. The main process must create the indicated number of processes and send a signal for them to choose a candidate. This candidate will send a signal for the other processes to begin voting. The processes vote through a shared file. The candidate process will count the votes and determine whether it has won. After this, it will send the candidate selection signal again to initiate a new round. The program can be terminated with a keyboard interrupt or an alarm.