【问题标题】:sigwait() repeatedly unblocked by SIGUSR1sigwait() 多次被 SIGUSR1 解除阻塞
【发布时间】:2014-12-22 11:51:11
【问题描述】:

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

用法:> 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()。没有变化。

【问题讨论】:

  • "... SIGUSR1 被重复调用" 未调用信号。请问您到底想表达什么?
  • 尝试使用sigaction 而不是signal
  • @alk:我希望在初始化后立即为命令发出信号。我希望在所有命令完全初始化后解除对信号的阻塞。
  • @mnunberg:试过了,没变。
  • 您应该在execvp() 之后添加代码以报告错误并退出,以防execvp() 返回(又名失败)。就目前而言,如果一个命令失败,它将继续退出其他命令。也许您的 on_sigusr1() 函数也应该报告 PID?在尝试使多进程系统正常工作时,报告 PID 通常会很有帮助。请注意,fclose(file);return 0; 之前的 exit(0); 使后两个语句无关紧要。我会删除exit(0);。另外,您能否显示您正在从中读取/执行命令的数据文件的前几行?

标签: c process operating-system signals


【解决方案1】:

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

所以也许放

int 信号;

int 结果 = sigwait(&sigset, &sig);

在 if 语句中检查 pid 是否 == 0,这表明它是一个孩子。否则,您将等待父进程。

如果 pid 大于 0 则为父进程 ID,如果小于 0 则为错误。

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

【讨论】:

  • 这个例子完全是一团糟。分叉子开始执行父代码,而父代码是 execvp 子代码。它应该只是在启动时崩溃。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-07
  • 2016-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多