gpt4 book ai didi

c++ - SIGINT 信号在写入管道期间被丢弃

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:43:13 31 4
gpt4 key购买 nike

我有一个程序使用 pcap_dump 函数将使用 libpcap 收集的 pcap 数据转储到标准输出,标准输出作为文件 *。需要对 SIGINT 进行一些清理,所以我使用 sigaction() 来处理它。这在从 shell 执行时效果很好。

但是,这个程序本来是要被另一个程序调用的,好像不行。这个“调用者”程序先调用一个 pipe(),然后调用一个 fork(),然后子进程的 stdout 文件描述符被关闭,并替换为管道的写入端。最后在子进程中执行前述的pcap程序。这样pcap数据就通过管道写入了调用程序。这也很好用。但是,当我向正在写入管道的子进程发送一个 SIGINT 时(好吧,pcap 程序认为它正在写入 stdout,但它的文件描述符已更改),信号似乎被丢弃,并且信号处理函数根本不会被调用。

这是为什么呢?如果我将 pcap 数据写入 stderr 或文件,则 SIGINT 永远不会被删除。仅在写入管道时。

下面是我们如何设置管道/分支/执行:

int fd[2];

//Create pipe
pipe(fd);

pid = fork(); //We forked a child

if(pid == 0){ //We are the child now

close(1); //close child's stdout

dup(fd[1]); //duplicate child's stdout to the write end of the pipe

close( fd[0]); //close unused file descriptors
close( fd[1]);

//Load the new program
execlp("./collectraw", "collectraw", NULL);

perror("Exec");
exit(127); //Should never get called but we leave it so the child
//doesnt accidently keep executing
}
else{ //We are the parent

//Set up the file descriptors
close(fd[1]);
}

然后杀死我们使用的 child :

kill( pid, SIGINT);

在 child 中,我们的 pcap_loop() 的回调函数可以很简单:

void got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet){
write(1,"<pretend this is like a thousand zeros>",1000); //write to stdout, which is really a pipe
}

而且我们基本上总是会丢弃 SIGINT。顺便说一句,有很多数据包要捕获,所以可以很安全地假设它几乎总是在回调函数中。

但是如果我们改变从

write(1,... ); //write to stdout, which is really a pipe

write(2,...); //write to stderr, or writing to a file would work too

然后一切又变得平淡无奇了。

为什么我们的 SIGINT 在写入管道期间被丢弃?

感谢您的帮助。

编辑: child 的 SIGINT 处理程序根本没有被调用,但原因并不是 child 的问题,而是 parent 的问题。我曾经像这样杀死 child :

if( kill( pid, SIGINT) == -1){
perror("Could not kill child");
}
close(pipefd);
fprintf(stdout, "Successfully killed child\n");

这曾经是我们的 SIGCHLD 处理程序:

void handlesigchild(int sig) {
wait();

printf("Cleaned up a child\n");
}

因此,如接受的答案中所述,立即关闭管道会导致我们的 child 在处理 SIGINT 之前使用 SIGPIPE 退出。我们刚刚将 close(pipefd) 移动到 SIGCHLD 处理程序,它现在可以工作了。

最佳答案

您没有显示足够多的代码来了解发生了什么。你应该总是尝试构造一个 SSCCE如果您希望人们能够对您的程序发表评论,请将其发布。

最佳猜测:您的 parent 在发送信号后退出,关闭管道的读取端。这会导致客户端在有机会处理 SIGINT 之前立即退出并发出 SIGPIPE。也尝试在 SIGPIPE 上进行清理,或者忽略 SIGPIPE。

关于c++ - SIGINT 信号在写入管道期间被丢弃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30519999/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com