【问题标题】:signal handler reading incorrect value信号处理程序读取不正确的值
【发布时间】:2015-03-09 10:57:40
【问题描述】:

在接收到 SIGUSR1 信号时,我想显示孩子从管道中读取的值。

有一个小问题。尽管 getppid() 已由父进程写入管道,但它始终显示 0。有什么解决办法吗? `

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

char bufP[10], bufC[10];
int gpid;

void handler(int signum){
    signal(SIGUSR1, handler);
    if (signum == SIGUSR1){
        printf("SIGUSR1 received\n");
        gpid = atoi(bufC);
        printf("Grandparent: %d\n", gpid);
        exit(0);
    }   
}

int main(void){
    int pid, fd[2];
    pipe(fd);
    pid = fork();

    signal(SIGUSR1, handler);

    if (pid == 0){
        //child
        close(fd[1]);       
        read(fd[0], bufC, sizeof(bufC));                
        close(fd[0]);
    }else{
        //parent
        close(fd[0]);
        sprintf(bufP, "%d", getppid());
        write(fd[1], bufP, sizeof(bufP));
        kill(pid, SIGUSR1);     
        close(fd[1]);
    }

}

`

感谢您的回复。

【问题讨论】:

标签: c signals fork


【解决方案1】:

您似乎认为信号将始终在read() 完成后处理,但事实并非如此。信号本质上是异步的,并且可以随时到达(甚至在 read()! 的中途)。基本上你是在所谓的竞态条件上构建你的程序,你真的应该避免这种情况。

【讨论】:

  • 通过设置信号处理程序分叉子节点后引入了第二场比赛。
  • 此外,孩子可能已经在 执行任何写入、发送或传递信号之前结束。
  • @alk:当然有,我什至不明白为什么 OP 也在父级中设置信号处理程序。但我看不出孩子如何在write() 执行之前结束,因为它将在read() 调用中被阻止,直到数据可用。不过,它可能会在信号发送之前结束,我同意这一点。
  • 正确,read() 阻止了孩子。所以孩子肯定不会在父母的写结束之前结束。我的错。
【解决方案2】:

虽然这里肯定存在竞争条件,但这并不是造成麻烦的原因。问题是在子进程中的 read() 调用被阻塞时触发了您的信号。您可以在父进程中添加足够长的暂停以让子进程的 read() 完成:

if (pid == 0){
    //child
    close(fd[1]);       
    read(fd[0], bufC, sizeof(bufC));                
    close(fd[0]);
    sleep(10); // wait for the signal to arrive
}else{
    //parent
    close(fd[0]);
    sprintf(bufP, "%d", getppid());
    write(fd[1], bufP, sizeof(bufP));
    close(fd[1]); // close right away to be sure the buffers are flushed
    sleep(1); // make sure the child has finished reading the buffer
    kill(pid, SIGUSR1);     
}

当然,关于竞争条件的评论以及您应该避免它们的事实仍然是正确的。此代码不是“生产质量”,如果您的系统上的负载太重以至于 1 秒不足以安排子进程并完成该 read() 调用,它将失败。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-15
    • 1970-01-01
    • 2012-01-19
    • 2022-12-23
    • 1970-01-01
    相关资源
    最近更新 更多