[英]SIGPIPE in a simple two process program
我為以前使用過的叉子和煙斗做了一個簡單的設置。 但是這次我在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()
,現在還不清楚是怎么回事。 有問題,但大多數沒有顯示塞子。
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( 簡短,自包含,正確的示例 )時,這很麻煩。 當測試用例簡化為可以編譯並運行的程序時,提交者確信問題會重現,這將變得非常容易。
此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'
的字符串。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.