
Dear GHC team,
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.
The C program fifo2 opens toA for reading,
opens fromA for writing,
inputs a string from toA,
prints "done" to the screen
(fromA is not really used, but will be needed in future).
The effect is that fifo2 (on terminal-2) hangs silent, while
Main.hs (on terminal-1) does its part.
If I remove the fopen(..fromA..)
call in fifo2.c, then it runs as expected
(after this example is fixed, fifo2 will need to write 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 source is quite small:
-- Main.hs ---------------------------------------------------------
import System.IO (IOMode(..), IO(..), Handle, openFile, hPutStr,
hFlush)
dir = showString "/home/mechvel/ghc/notes/npipe/"
toA_IO = openFile (dir "toA") WriteMode :: IO Handle
fromA_IO = openFile (dir "fromA") ReadMode
axiomIO :: Handle -> String -> IO()
axiomIO h str = do
hPutStr h str
hFlush h
putStr "hFlush done\n"
main = do
h <- toA_IO
putStr "str1 --> "
axiomIO h "A1\n"
----------------------- fifo2.c -------------------------------------
#include

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." In the sister thread in haskell-cafe, the addition of unsafePerformIO throws further disorder into these highly order-sensitive operations.

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@botik.ru)
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.
Regards,
------
Sergei
mechvel@botik.ru
********************************************************************
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 =
do
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

On 12-01-19 02:16 PM, Serge D. Mechveliani wrote:
-- Main.hs --------------------------------------------------------- hPutStr h1 str hFlush h1
This fails to send a newline.
----------------------- fifo2.c ------------------------------------- if (fgets(str, BOUND, toA) == NULL) {
This refuses to finish until it sees a newline (or BOUND chars, or the eof condition, or an error condition). What really interests me is that if Main.hs is linked with -threaded, the deadlock is unlocked, and both programs proceed to completion. This is because the -threaded runtime goes through garbage collection when idling (such as waiting for hGetLine). Since there is no further reference to h1 by then, GC hCloses it. That unlocks the fgets side. This is fragile and not to be relied on. You will always have further references to h1 in practice.
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'.
I am not convinced in the case of fgets. I cannot reproduce it. (Oh, I know read has a much better chance, it doesn't wait for a newline.)
participants (2)
-
Albert Y. C. Lai
-
Serge D. Mechveliani