Read on closed named pipe blocks

时间:2015-11-12 11:47:55

标签: c io fortran named-pipes

I am trying to read from a named pipe (FIFO) with Fortran. Reading the data works, but the Fortran program does not seem to notice when the pipe is closed on the other end; reads simply block rather than getting an EOF.

Sample program:

program kitten
  character(256) :: buf

  open(22, file='test')
  do
     read(22, *) buf
     print*, trim(buf)
  end do
end program kitten

Now with

$ mkfifo test
$ echo -e '1\n2\n3' >test &
$ ./kitten

the program prints 1\n2\n3\n as expected, but then simply hangs.

Instead, the program returns an error on EOF if

  1. test is a regular file; or
  2. you change kitten to read from STDIN and do ./kitten <test or
  3. echo -e '1\n2\n3' | ./kitten; or
  4. you write an equivalent kitten program in C.

I tested this with ifort 15.0.1 and gfortran 4.9.2, with the same results.

For C I used gcc and

#include <stdio.h>

main() {
        char buf[256];
        FILE *test;

        test = fopen("test", "r");

        while(fgets(buf, 256, test)) {
                printf(buf);
        }
}

2 个答案:

答案 0 :(得分:4)

我对Fortran一无所知,但我知道你可以通过在开放时使用读/写模式重现C中的悬挂行为(例如{"action": "notifyEmail", "serverId": "00000000000001", "email": "youremail@host.com", "description": "Memory usage is higher than 95%"}

管道没有得到EOF,直到它上面的可写文件描述符数量减少为0.当你的读取文件描述符也可写时,你永远不会得到EOF。

所以我的猜测是Fortran默认以读/写模式打开,你需要告诉它不要这样做。 This question about a fortran readonly flag可能有帮助。

答案 1 :(得分:0)

关于C程序。

更好的版本是:

#include <stdio.h>
#include <stdlib.h>  // exit(), EXIT_FAILURE

int main( void ) // properly declare main()
{
    char buf[256];
    FILE * test = NULL;

    if( NULL == (test = fopen("test", "r") ) ) // check for open error
    { // then fopen failed
        perror( "fopen for test for read failed");
        exit( EXIT_FAILURE );
    }

    // implied else, fopen successful

    while(fgets(buf, 256, test) ) // exit loop when fgets encounters EOF
    {
        printf("%s\n",buf);
    }

    fclose( test ); // cleanup before exiting
    return 0; // properly supply a return value
}