1

以前に使用したフォークとパイプの簡単なセットアップがあります。しかし、今度は電話がかかっ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);

    }
}
4

1 に答える 1

2

パイプに書き込むときにSIGPIPEを取得する場合は、パイプから読み取ることができるプロセスがないことを意味します。現在のプロセス(パイプの読み取り端を閉じています。これは良いことです。代わりにデッドロックになります)もありません。あなたがそれを閉じなかったなら死んだ)または他の(子)プロセス。

関数が何をするのかを示していないのでfoo()、何が悪いのかについてはこれ以上お話しできません。


これfoo()が追加されたので、何が起きているのかは明確ではありません。問題はありますが、ほとんどはショーストッパーではありません。

  1. 引数dirnameは未使用です。
  2. 引数outは未使用です。
  3. sepループ内で割り当てられたメモリをリークします。
  4. パイプから読み取られた文字列がnullで終了することを保証しません。これによりクラッシュが発生し、書き込みが失敗する可能性があります。

項目4はすぐに重大な問題だと思います。他のものはより整頓の問題です。

メインコードには、次のものがあることに注意してください。

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

MAXWORD4または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

'\0'文字列の最後にあるWHATがパイプに書き込まれ、パイプから読み取られるため、これが機能することに注意してください。ほとんどの場合、末尾のを含む文字列は記述しません'\0'

于 2013-03-18T16:54:01.373 に答える