我有一个简单的设置,我之前使用过叉子和管道。但这一次我在SIGPIPE
电话中收到了write
。这是代码
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);
}
}
答案 0 :(得分:2)
如果在管道上写入时收到SIGPIPE,则表示没有可以从管道读取的进程:当前进程(您已关闭管道的读取端 - 这是好的;您是如果你没有关闭它,那么就会陷入僵局,而不是另一个(孩子)过程。
由于您没有显示foo()
函数的功能,我们无法告诉您更多有关错误的信息。
现在添加了foo()
,目前还不清楚是什么。有问题,但大多数都没有显示停止者。
dirname
未使用。out
未使用。sep
的内存。我怀疑第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
请注意,这是有效的,因为字符串'\0'
末尾的WHAT
被写入管道,并从管道中读取。通常,您不会编写包含尾随'\0'
的字符串。