簡體   English   中英

SIGPIPE在一個簡單的兩處理程序中

[英]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() ,現在還不清楚是怎么回事。 有問題,但大多數沒有顯示塞子。

  1. 參數dirname未使用。
  2. out未使用。
  3. 您會在循環中泄漏分配給sep的內存。
  4. 您不能確保從管道讀取的字符串以null結尾。 這可能會導致崩潰,進而導致寫入失敗。

我懷疑第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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM