2014-10-27 10 views
5

Sto scrivendo un programma che prende un elenco di comandi UNIX da un file e li esegue in sequenza. Per mantenere tutto in ordine, devo avere inizializzato ogni comando e ho continuato ad aspettare SIGUSR1 tramite sigwait(). Quando ogni comando è inizializzato, allora ogni comando può essere eseguito.sigwait() sbloccato ripetutamente da SIGUSR1

Usage: > program.c input.txt

Tuttavia, sembra che SIGUSR1 viene ripetutamente chiamato, superando completamente sigwait(). Che cosa sta succedendo qui? Ho provato tante cose diverse, ma è stato modellato di recente dopo this answer. Per riformulare, voglio che il segnale venga generato per i comandi immediatamente dopo l'inizializzazione. Voglio che il segnale da sbloccata quando tutti i comandi sono completamente inizializzati

#include <stdio.h> 
#include <signal.h> 
#include <string.h> 
#include <stdlib.h> 
#include <unistd.h> 


void on_sigusr1(int sig) 
{ 
// Note: Normally, it's not safe to call almost all library functions in a 
// signal handler, since the signal may have been received in a middle of a 
// call to that function. 
    printf("SIGUSR1 received!\n"); 
} 

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


    FILE *file; 
    file = fopen(argv[1] ,"r"); 

    int BUF_SIZE = 100; 

    char *token; 
    char buffer[BUF_SIZE]; 
    char programs[BUF_SIZE]; 
    char *commands[BUF_SIZE]; 

    int i = 0; 
    int counter = 1; 

    while (fgets(buffer, sizeof buffer, file) != NULL) 
    { 
     strcpy(programs, buffer); 

     int length = strlen(buffer)-1; 
     if (buffer[length] == '\n') 
     { 
      buffer[length] = '\0'; 
     } 

     i = 0; 
     token = strtok(buffer," "); 
     while(token != NULL) 
     { 
      commands[i++] = token; 
      token = strtok(NULL, " "); 
     } 
     commands[i] = 0; 

     pid_t pids[counter]; 


     // Set a signal handler for SIGUSR1 
     signal(SIGUSR1, &on_sigusr1); 

    // At program startup, SIGUSR1 is neither blocked nor pending, so raising it 
    // will call the signal handler 
     raise(SIGUSR1); 

    // Now let's block SIGUSR1 
     sigset_t sigset; 
     sigemptyset(&sigset); 
     sigaddset(&sigset, SIGUSR1); 
     sigprocmask(SIG_BLOCK, &sigset, NULL); 

    // SIGUSR1 is now blocked, raising it will not call the signal handler 
     printf("About to raise SIGUSR1\n"); 
     raise(SIGUSR1); 
     printf("After raising SIGUSR1\n"); 


     for(i = 0; i < counter; ++i) 
     { 
      pids[i] = fork(); 

      if(pids[i] > 0) 
      { 
       printf("Child process %d ready to execute command %s", getpid(), programs); 
       // SIGUSR1 is now blocked and pending -- this call to sigwait will return 
       // immediately 
       int sig; 
       int result = sigwait(&sigset, &sig); 
       if(result == 0) { 
        printf("Child process %d executing command %s", getpid(), programs); 
        execvp(commands[0], commands); 
       } 
      } 
     } 

     // All programs have been launched 
     for(i = 0; i < counter; ++i) 
     { 
      wait(&pids[i]); 
     } 

     // All programs are waiting to execute 
     for (i = 0; i < counter; ++i) 
     { 
     // SIGUSR1 is now no longer pending (but still blocked). Raise it again and 
     // unblock it 
      raise(SIGUSR1); 
      printf("About to unblock SIGUSR1\n"); 
      sigprocmask(SIG_UNBLOCK, &sigset, NULL); 
      printf("Unblocked SIGUSR1\n"); 
     } 
    } 

exit(0); 
fclose(file); 
return 0; 
} 

UPDATE: provato a cambiare signal()-sigaction(). Nessun cambiamento.

+0

"* ... SIGUSR1 viene ripetutamente chiamato *" non viene chiamato un segnale. Per favore cosa vuoi esprimere esattamente? – alk

+1

Prova a usare 'sigaction' invece di' signal'. –

+0

@alk: desidero che il segnale venga generato per i comandi immediatamente dopo l'inizializzazione. Voglio che il segnale sia sbloccato quando tutti i comandi sono completamente inizializzati. –

risposta

1

È necessario prendere in considerazione la possibilità di chiamare sigwait dopo il per verificare se il pid è un processo figlio.

Quindi forse inserire

int sig;

e

int risultato = sigwait (& sigset, & sig);

all'interno di un'istruzione if che controlla se il pid è == 0 che indica che si tratta di un figlio. Altrimenti staresti firmando un processo genitore.

Se il pid è maggiore di 0 è un id del processo principale e se è inferiore a zero è un errore.

Quindi per ogni processo nella serie di pid si chiamerebbe kill (pid_array [i], SIGUSR1) per sbloccarlo.

+0

questo esempio è un totale disordine. Forking child che inizia ad eseguire il codice genitore, mentre padre è execvp childs code .. Dovrebbe semplicemente bloccarsi all'avvio. – Nazar