This patch fixes a regression in stream output to fifos (named pipes). When a fifo is opened for output, the process should block until another process opens the fifo for reading. This is now (again) the case.
Tested on x86_64-pc-linux-gnu, committed on trunk 2016-04-18 Bob Duff <d...@adacore.com> * s-fileio.adb (Fopen_Mode): If Mode = Out_File, and the file exists, and it's a fifo, we use "w" as the open string instead of "r+". This is necessary to make a write to the fifo block until a reader is ready.
Index: cstreams.c =================================================================== --- cstreams.c (revision 235093) +++ cstreams.c (working copy) @@ -39,6 +39,8 @@ #include <stdio.h> #include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> #ifdef _AIX /* needed to avoid conflicting declarations */ @@ -320,6 +322,24 @@ } #endif +/* Returns true if the path names a fifo (i.e. a named pipe). */ +int +__gnat_is_fifo (const char* path) +{ +/* Posix defines S_ISFIFO as a macro. If the macro doesn't exist, we return + false. */ +#ifdef S_ISFIFO + struct stat buf; + const int status = stat(path, &buf); + if (status == 0) + return S_ISFIFO(buf.st_mode); +#endif + + /* S_ISFIFO is not available, or stat got an error (probably + file not found). */ + return 0; +} + #ifdef __cplusplus } #endif Index: s-fileio.adb =================================================================== --- s-fileio.adb (revision 235093) +++ s-fileio.adb (working copy) @@ -106,17 +106,18 @@ -- Holds open string (longest is "w+b" & nul) procedure Fopen_Mode - (Mode : File_Mode; + (Namestr : String; + Mode : File_Mode; Text : Boolean; Creat : Boolean; Amethod : Character; Fopstr : out Fopen_String); -- Determines proper open mode for a file to be opened in the given Ada - -- mode. Text is true for a text file and false otherwise, and Creat is - -- true for a create call, and False for an open call. The value stored - -- in Fopstr is a nul-terminated string suitable for a call to fopen or - -- freopen. Amethod is the character designating the access method from - -- the Access_Method field of the FCB. + -- mode. Namestr is the NUL-terminated file name. Text is true for a text + -- file and false otherwise, and Creat is true for a create call, and False + -- for an open call. The value stored in Fopstr is a nul-terminated string + -- suitable for a call to fopen or freopen. Amethod is the character + -- designating the access method from the Access_Method field of the FCB. function Errno_Message (Name : String; @@ -433,10 +434,14 @@ -- OPEN CREATE -- Append_File "r+" "w+" -- In_File "r" "w+" - -- Out_File (Direct_IO, Stream_IO) "r+" "w" + -- Out_File (Direct_IO, Stream_IO) "r+" [*] "w" -- Out_File (others) "w" "w" -- Inout_File "r+" "w+" + -- [*] Except that for Out_File, if the file exists and is a fifo (i.e. a + -- named pipe), we use "w" instead of "r+". This is necessary to make a + -- write to the fifo block until a reader is ready. + -- Note: we do not use "a" or "a+" for Append_File, since this would not -- work in the case of stream files, where even if in append file mode, -- you can reset to earlier points in the file. The caller must use the @@ -458,7 +463,8 @@ -- to the mode, depending on the setting of Text. procedure Fopen_Mode - (Mode : File_Mode; + (Namestr : String; + Mode : File_Mode; Text : Boolean; Creat : Boolean; Amethod : Character; @@ -466,6 +472,9 @@ is Fptr : Positive; + function is_fifo (Path : Address) return Integer; + pragma Import (C, is_fifo, "__gnat_is_fifo"); + begin case Mode is when In_File => @@ -479,7 +488,10 @@ end if; when Out_File => - if Amethod in 'D' | 'S' and then not Creat then + if Amethod in 'D' | 'S' + and then not Creat + and then is_fifo (Namestr'Address) = 0 + then Fopstr (1) := 'r'; Fopstr (2) := '+'; Fptr := 3; @@ -1045,7 +1057,7 @@ else Fopen_Mode - (Mode, Text_Encoding in Text_Content_Encoding, + (Namestr, Mode, Text_Encoding in Text_Content_Encoding, Creat, Amethod, Fopstr); -- A special case, if we are opening (OPEN case) a file and the @@ -1218,7 +1230,7 @@ else Fopen_Mode - (Mode, File.Text_Encoding in Text_Content_Encoding, + (File.Name.all, Mode, File.Text_Encoding in Text_Content_Encoding, False, File.Access_Method, Fopstr); File.Stream := freopen