sigwait()反复解除SIGUSR1的阻塞

时间:2014-10-27 10:13:34

标签: c process operating-system signals

我正在编写一个程序,它从文件中获取UNIX命令列表并按顺序执行它们。为了保持一切顺序,我必须初始化每个命令,并通过SIGUSR1等待sigwait()。初始化每个命令时,每个命令都可以执行。

用法:> program.c input.txt

然而,似乎反复调用SIGUSR1,完全超越sigwait()。这里发生了什么?我尝试了很多不同的东西,但它最近是在this answer之后建模的。换句话说,我希望在初始化后立即为命令引发信号。我想在所有命令完全初始化时解锁信号

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

更新:尝试将signal()更改为sigaction()。没有变化。

1 个答案:

答案 0 :(得分:1)

您应该考虑在检查后调用sigwait 以查看该pid是否为子进程。

所以也许放

int sig;

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

在if语句中检查pid是否为== 0,这表明它是一个孩子。否则你会在sigwaiting一个父进程。

如果pid大于0,则它是父进程id,如果它小于零,则表示错误。

然后对于你的pids数组中的每个进程,你会调用kill(pid_array [i],SIGUSR1)来解除阻塞。