gpt4 book ai didi

c - SIGPIPE中一个简单的二进程程序

转载 作者:太空宇宙 更新时间:2023-11-04 02:57:44 25 4
gpt4 key购买 nike

我有一个简单的 fork 和管道设置,我以前用过。但这次我在 write 调用中收到了一个 SIGPIPE。这是代码

int fd[2];

int pid;

if (pipe(fd) == -1) {
perror("pipe init error");
exit(1);
}


// signal(SIGPIPE, SIG_IGN);
if ((pid = fork()) < -1) {
perror("fork error"); exit(1);
}
// parent
else if (pid > 0) {
close(fd[0]);

write(fd[1], "WHAT", MAXWORD); //SIGPIPE here

close(fd[1]);
int status;
wait(&status);
}

// child
else {
close(fd[1]);
// void foo(char *dirname, int in, int out);
// foo takes a path, reads from fd 'in' and outputs to 'fd' out
foo("./some/path", fd[0], 1);
close(fd[0]);
}

这里是 foo 函数:

void foo(char *dirname, int in, int out){

int string_length;
char word[MAXWORD];

// to get rid of \n
char* sep;
sep = malloc(sizeof(char));


// read from piped stdin until it's closed
while ((string_length = read(in, word, MAXWORD)) > 0){

// get rid of \n
sep = strchr(word, '\n');
*sep = '\0';

printf("THe word is: %s\n", word);

}
}

最佳答案

如果在管道上写入时收到 SIGPIPE,这意味着没有进程可以从管道读取:当前进程也没有(您已经关闭了管道的读取端——这很好;您会死锁而不是死,如果你不关闭它)或其他(子)进程。

由于您没有展示函数 foo() 的作用,我们无法告诉您更多有关错误的信息。


现在添加了foo(),不清楚是怎么回事。有问题,但大多数都不是阻碍。

  1. 参数 dirname 未使用。
  2. 参数 out 未使用。
  3. 您在循环中泄漏了分配给 sep 的内存。
  4. 您不确保从管道读取的字符串以空字符结尾。这可能会导致崩溃,进而导致写入失败。

我怀疑第 4 项是紧迫的关键问题;其他更多的是整洁问题。

我注意到在主要代码中,您有:

write(fd[1], "WHAT", MAXWORD); //SIGPIPE here

除非 MAXWORD 为 4 或 5,否则您将走上失败之路;你应该只写 4 或 5 个字符。

结合 read()...读取将尝试读取 MAXWORD 字节,但可能会更少。但是,没有迹象表明写入的数据包含换行符,因此在输入中搜索换行符不会可靠地工作。然而,这个问题应该在管道成功写入之后才会出现,而不是之前。

我注意到变量 int fd_parent_write_word[2]; 未使用,代码使用了变量 int fd[2] 而未声明它。

当您要分析的不是 SSCCE (Short, Self-Contained, Correct Example) 时,这很麻烦。当测试用例被简化为一个可以编译和运行的简单程序时,提交者确信问题会重现,这就容易多了。


此 SSCCE 代码编译干净并运行正常:

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

enum { MAXWORD = 5 };

static void foo(int in);

static void he_who_pays_the_piper(int signum)
{
assert(signum == SIGPIPE);
const char msg[] = "Received signal SIGPIPE\n";
write(2, msg, sizeof(msg)-1);
exit(1);
}

int main(void)
{
int fd[2];
int pid;

if (pipe(fd) == -1) {
perror("pipe init error");
exit(1);
}

signal(SIGPIPE, he_who_pays_the_piper);
if ((pid = fork()) < -1) {
perror("fork error"); exit(1);
}
else if (pid > 0) {
close(fd[0]);
write(fd[1], "WHAT", MAXWORD); //SIGPIPE here
close(fd[1]);
int status;
pid = wait(&status);
printf("Got status 0x%04X from %d\n", status, pid);
}
else {
close(fd[1]);
foo(fd[0]);
close(fd[0]);
}
return 0;
}


static void foo(int in)
{
int string_length;
char word[MAXWORD];

while ((string_length = read(in, word, MAXWORD)) > 0)
printf("The word is: %.*s\n", string_length, word);
}

示例输出:

The word is: WHAT
Got status 0x0000 from 49458

请注意,这是有效的,因为字符串 WHAT 末尾的 '\0' 被写入管道,并从管道中读取。大多数情况下,您不会编写包含尾随 '\0' 的字符串。

关于c - SIGPIPE中一个简单的二进程程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15482349/

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