2012-08-02 13 views
8

Estoy tratando de obtener una aplicación fortran 90 para abrir una fifo y escribir datos formateados en ella. Lo he reducido a un ejemplo mínimo. Vamos foo.f90 ser el siguiente programa:Escribir a fifo (named pipe)

program foo 
    open(1,file='fifo',position='asis',action='write') 
    write(1,*)'Hello, world!' 
    write(1,*)'Goodbye.' 
end program 

Ahora compilar y ejecutar el programa:

$ gfortran-4.7.1 -o foo foo.f90 
$ rm -f fifo 
$ ./foo 
$ cat fifo 
Hello, world! 
$ rm -f fifo 
$ mkfifo fifo 
$ cat fifo > bar & 
[1] 6115 
$ strace -o foo.st ./foo 
At line 3 of file foo.f90 (unit = 1, file = 'fifo') 
Fortran runtime error: Invalid argument 
[1]+ Done     cat fifo > bar 
$ tail foo.st 
write(3, " Hello, world!\n", 15)  = 15 
lseek(3, 0, SEEK_CUR)     = -1 ESPIPE (Illegal seek) 
ftruncate(3, 18446744073709551615)  = -1 EINVAL (Invalid argument) 
write(2, "At line 3 of file foo.f90 (unit "..., 52) = 52 
write(2, "Fortran runtime error: ", 23) = 23 
write(2, "Invalid argument", 16)  = 16 
write(2, "\n", 1)      = 1 
close(3)        = 0 
exit_group(2)       = ? 
+++ exited with 2 +++ 

Así que el programa funciona bastante bien cuando se escribe en un archivo normal. Sin embargo, al escribir en la fifo, intenta cambiar el tamaño del archivo después de la primera escritura, terminando la aplicación después de no hacerlo.

Soy bastante nuevo en Fortran, así que no estoy seguro de si esto es un error en gfortran, o si hay alguna manera de abrir el archivo que suprimirá este ftruncate syscall. Preferiría seguir con el enfoque secuencial formateado: mis líneas tienen diferentes longitudes, y prefiero evitar tener que especificar un número de registro con cada write.

Respuesta

4

Ésta es una old feature (ni siquiera se atreven a pensar que es un error!) En libgfortran que fue parcheado hace versiones pero fue reintroducido para el GCC 4.7 rama, más específicamente en el SVN revision 180701. Aparentemente, los desarrolladores de gfortran no prueban su código de E/S con conductos con nombre.

Debe usar una versión anterior gfortran (funciona con 4.6.1) u otro compilador Fortran de un proveedor diferente. Presentaré un informe de error a GCC.

+1

Usando 'gfortran-4.6.3' aparece el mismo comportamiento. 'gfortran-4.1.2' falla con' Ilegal seek', es decir, un syscall anterior. 'gfortran-4.2.4' en realidad parece funcionar como se esperaba, pero no admitirá el código en mi aplicación real. Cuando envíe un error, hágamelo saber su URL para que pueda suscribirme también. – MvG

+1

Funciona con 'gfortran' 4.6.1. Era demasiado perezoso para comprobar realmente a qué etiqueta pertenece r180701 y simplemente asumí que no se realizan cambios importantes entre las versiones menores. –

+0

@MvG, hice un nuevo comentario sobre el error anterior. Veamos que pasa. –