信号处理程序读取不正确的值

signal handler reading incorrect value

收到 SIGUSR1 信号后,我想显示 child 从管道读取的值。

有个小问题。尽管 parent 进程将 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]);
    }

}

`

感谢您的回复。

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

虽然这里肯定存在竞争条件,但这并不是造成麻烦的原因。问题是当 child 进程中的 read() 调用被阻塞时,您的信号被触发。您可以在 parent 过程中添加足够长的暂停,让 child 的 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);     
}

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