Sigwait () is repeatedly unlocked by SIGUSR1

I am writing a program that takes a list of UNIX commands from a file and executes them sequentially. For everything to be in order, I have to initialize each command and continue to wait for SIGUSR1 via sigwait() . When each command is initialized, each command can execute.

Usage: > program.c input.txt

However, it seems that SIGUSR1 is repeatedly called, completely surpassing sigwait() . What's going on here? I tried so many different things, but he recently modeled after this answer . To rephrase, I want the signal to be raised for commands immediately after initialization. I want the signal to be unlocked when all commands are fully initialized

 #include <stdio.h> #include <signal.h> #include <string.h> #include <stdlib.h> #include <unistd.h> void on_sigusr1(int sig) { // Note: Normally, it 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 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: tried to change signal() to sigaction() . Without changes.

+5
source share
1 answer

You should consider calling sigwait after to see if this pid is a child process.

So maybe put

int sig;

and

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

inside an if statement, which checks if pid == 0, which indicates that it is a child. Otherwise, you will expect from the parent process.

If pid is greater than 0, this is the parent identifier of the process, and if it is less than zero, its error.

Then for each process in your pids array, you can call kill (pid_array [i], SIGUSR1) to unlock it.

+1
source

Source: https://habr.com/ru/post/1205596/


All Articles