2013-03-18 49 views
1

我有一個簡單的設置叉和管,我以前使用過。但是這一次,我在write調用中收到SIGPIPE。下面的代碼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); 

    } 
} 

回答

2

如果您在寫在管弄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 

注意這是因爲'\0'在字符串WHAT結束寫入管道,並從管道讀取。大多數情況下,你不會寫下包括尾部'\0'在內的字符串。

+0

我會在我的編輯中張貼foo – kayvanmsh 2013-03-18 16:57:11

+0

謝謝!我得到了它的工作 – kayvanmsh 2013-03-18 22:16:06

相關問題