2014-10-27 5 views
5

Ich schreibe ein Programm, das eine Liste von UNIX-Befehlen aus einer Datei nimmt und sie sequentiell ausführt. Um alles in Ordnung zu halten, muss ich jeden Befehl initialisiert haben und auf SIGUSR1 über warten. Wenn jeder Befehl initialisiert ist, kann jeder Befehl ausgeführt werden.sigwait() wiederholt von SIGUSR1 entsperrt

Verbrauch: > program.c input.txt

Allerdings scheint es, dass SIGUSR1 wiederholt, vollständig sigwait() übertraf genannt wird. Was geht hier vor sich? Ich habe so viele verschiedene Dinge ausprobiert, aber es wurde kürzlich nach this answer modelliert. Um neu zu formulieren, möchte ich das Signal für Befehle sofort nach der Initialisierung ausgelöst werden. Ich möchte das Signal freigegeben werden, wenn alle Befehle vollständig

#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 initialisiert werden: Versuchte signal()-sigaction() ändern. Keine Änderung.

+0

"* ... SIGUSR1 wird wiederholt *" ein Signal wird nicht aufgerufen. Bitte was genau willst du ausdrücken? – alk

+1

Versuchen Sie, 'sigaction' anstelle von' signal' zu verwenden. –

+0

@alk: Ich möchte das Signal für Befehle sofort nach der Initialisierung ausgelöst werden. Ich möchte, dass das Signal entsperrt wird, wenn alle Befehle vollständig initialisiert sind. –

Antwort

1

Sie sollten erwägen, sigwait nach zu überprüfen, um zu sehen, ob diese PID ein Kindprozess ist.

So setzen vielleicht

int sig;

und

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

innerhalb einer if-Anweisung, die überprüft, ob die PID == 0 ist, was anzeigen würde, dass es ein Kind ist. Sonst würden Sie einen Elternprozess sigwaiting.

Wenn die PID größer als 0 ist, ist es eine übergeordnete Prozess-ID, und wenn es kleiner als Null ist, ist es ein Fehler.

Dann würden Sie für jeden Prozess in Ihrem Array von PID kill (pid_array [i], SIGUSR1) aufrufen, um es zu entsperren.

+0

Dieses Beispiel ist ein totales Durcheinander. Forking Kind, das beginnt, Eltern Code auszuführen, während Eltern execvp Childs Code ist .. Es sollte nur beim Start abstürzen. – Nazar