Windows: Inconsistent hReady behavior between POSIX and native IO managers
While debugging a Windows-only issue with the sbv
library (see https://github.com/LeventErkok/sbv/issues/644), it was discovered that the hReady
function behaves inconsistently between IO managers on Windows. The following two programs attempt to minimize what goes on when sbv
communicates with an external process:
-- Producer.hs
module Main where
import System.IO
main :: IO ()
main = do
s <- getLine
putStrLn $ "Responding to: " ++ s
hFlush stdout
_ <- getLine
pure ()
-- Consumer.hs
module Main (main) where
import Control.Concurrent
import System.Environment
import System.Process
import System.IO
main :: IO ()
main = do
args <- getArgs
pgm <- case args of
[p] -> pure p
_ -> error "Pass the path to the producer executable"
(inp, out, _, _) <- runInteractiveProcess pgm [] Nothing Nothing
hPutStrLn inp "Hello"
hFlush inp
threadDelay 1000000
let collect = reverse <$> go ""
go sofar = do isReady <- hReady out
if isReady
then do c <- hGetChar out
go (c : sofar)
else pure sofar
s <- collect
putStrLn $ "Producer says: " ++ s
First, compile these programs with:
$ ghc-9.2.7 -fforce-recomp Producer.hs -rtsopts
$ ghc-9.2.7 -fforce-recomp Consumer.hs -rtsopts
Next, run the following command, first using the POSIX IO manager:
$ ./Consumer.exe ./Producer.exe +RTS --io-manager=posix -RTS
Producer says: Responding to: Hello
This is the expected result, and this is what happens on Mac and Linux as well.
Now run the same command, but with the native IO manager:
$ ./Consumer.exe ./Producer.exe +RTS --io-manager=native -RTS
Producer says:
This time, it simply prints out Producer says:
without any further output. This seems to indicate that the behavior of hReady
differs with the IO manager, which is not what I would expect.
I used GHC 9.2.7 above, but I get the same results with 9.4.4 and 9.6.1-alpha3 as well.