named pipes

Serge D. Mechveliani mechvel at
Thu Jan 19 20:16:30 CET 2012

To my 
>> Dear GHC team,
>> I am testing the IO operations of GHC with the Unix  named pipes
>> [..]

Albert Y. C. Lai  writes on 19 Jan 2012

> Main.hs  does not open fromA at all. (fromA_IO is dead code.) This causes
> fifo2.c to be hung whenever it opens fromA. From the man page of mkfifo(3)
> on Linux:
> "Opening a FIFO for reading normally blocks until some other process opens
> the same FIFO for writing, and vice versa. See fifo(7) for nonblocking
> handling of FIFO special files."

I see now. Thank you.
The intitial example was with a real usage of toA and fromA, and it did 
not work as expected. Then, I simplified it, but just missed the point 
that ./Main does not really open  fromA. 
Now, I provide below the initial example.

Can people explain, please, why it performs so? 

> In the sister thread in haskell-cafe, the addition of unsafePerformIO
> throws further disorder into these highly order-sensitive operations.

By the way, can you respond (if not to `glasgow' then to mechvel at
to my last simple and concrete question to  cafe  on the subject of   
unsafePerformIO ?

Anyway, the below example is free of  unsafePerformIO.
And I need to delay the remaining questions on  unsafePerformIO
(for myself and maybe, for `cafe') until the current example is fixed.


mechvel at

I am testing the IO operations of GHC with the Unix named pipes --
(in  ghc-7.01  under Debian Linux).

In the below example, 
the pipe pair are created by   > mkfifo toA
                               > mkfifo fromA,

`main'  in  Main.hs  opens  toA    for writing,
                     opens  fromA  for reading,
                     outputs  "A1"  to  toA,
                     inputs the respond string  str'  from  fromA,
                     prints  str'  to the screen.
The C program  fifo2  
      opens  toA    for reading,
      opens  fromA  for writing,
      inputs a string  str  from  toA,
      converts  str  to the lower case, obtaining  str'
      outputs  str'  to  fromA.

Main.hs       is built by   ghc --make Main,
The C program is built by   gcc -o fifo2 fifo2.c

First,  ./fifo2   is run on  terminal-2,
then    ./Main    is run on  terminal-1.

The effect is that   fifo2    (on terminal-2)  hangs silent, and
                     Main.hs  (on terminal-1)  reports only 
                          "str1  -->  hFlush done", and then hangs.

This contradicts to that  ./Main   must print  str'  to the screen.

The modules are as follows.

-- Main.hs ---------------------------------------------------------
import System.IO (IOMode(..), IO(..), Handle, openFile, hPutStr, 
                                                       hFlush, hGetLine)
dir = showString "/home/mechvel/ghc/notes/npipe/"

toA_IO   = openFile (dir "toA")   WriteMode   :: IO Handle
fromA_IO = openFile (dir "fromA") ReadMode  

axiomIO :: Handle -> Handle -> String -> IO String
axiomIO    h1        h2        str = 
           hPutStr h1 str 
           hFlush h1
           putStr "hFlush done\n"
           str' <- hGetLine h2
           putStr (concat ["hGetLine ->  ", str', "\n"])
           return str'
main = do
       h1 <- toA_IO
       h2 <- fromA_IO
       putStr "str1  -->  " 
       str1' <- axiomIO h1 h2 "A1"
       putStr (str1' ++ "\n")

----------------------- fifo2.c -------------------------------------
#include <stdio.h>
#include <string.h>  
#define BOUND 64
static  char  str[BOUND];

  int l, i;   FILE *toA, *fromA;

  toA = fopen("/home/mechvel/ghc/notes/npipe/toA", "r");
  if (toA == NULL) {perror("fopen(toA, r)  failed:  ");  return;};   
  fromA = fopen("/home/mechvel/ghc/notes/npipe/fromA", "w");
  if (fromA == NULL) {perror("fopen(fromA, w)  failed:  ");  return;};   

  if (fgets(str, BOUND, toA) == NULL) { 
     perror("fgets(str, bound, toA)  failed:  "); return;
  printf("input = %s\n", str);
  l = strlen(str) - 1; 
  i = 0;                       // convert the string to the lower case
  while (i < l) {str[i] = tolower(str[i]);  i++;}

  printf("output = %s\n", str);
  fputs(str, fromA);
  printf("output to fromA done\n");

Comparison with C - C
If both programs are in C, then the whole loop of the string exchange 
(with  fifo2.c  rewritten into a loop) works as needed, both for the 
variants with fgets and with `read'.

More information about the Glasgow-haskell-users mailing list