ndmitchell / ghcid

Very low feature GHCi based IDE
Other
1.13k stars 114 forks source link

Attempting to set stdin handle results in `*** Exception: <stdin>: hDuplicate: illegal operation (cannot flush the read buffer: underlying device is not seekable)` #274

Open chrissound opened 5 years ago

chrissound commented 5 years ago

Not sure if this is a bug or it's just the way ghcid works:

With ghcid

ghcid --test=Main.main Main.hs
Loading ghci -fno-break-on-exception -fno-break-on-error -v1 -ferror-spans -j Main.hs ...
GHCi, version 8.6.3: http://www.haskell.org/ghc/  :? for help
[1 of 1] Compiling Main             ( Main.hs, interpreted )
Ok, one module loaded.

All good (1 module, at 15:00:48)
Running test...
*** Exception: <stdin>: hDuplicate: illegal operation (cannot flush the read buffer: underlying device is not seekable)

While with ghci:

ghci Main.hs -e "main"
"test"
import qualified System.IO
import qualified GHC.IO.Handle

filename = "test.txt"                                                                                                                                                                                                                                                      
main = do
      h <- System.IO.openFile filename System.IO.ReadMode
      old_stdin <- GHC.IO.Handle.hDuplicate System.IO.stdin
      GHC.IO.Handle.hDuplicateTo h System.IO.stdin
      System.IO.hClose h
      realMain
      GHC.IO.Handle.hDuplicateTo old_stdin System.IO.stdin

realMain = do
  x <- getLine
  print x

The motivation for doing the above is essentially this question: https://stackoverflow.com/questions/50931355/how-can-i-test-a-program-reading-from-stdin-in-ghci/50932360

Complete repo here (just basically the file above): https://github.com/chrissound/GhciStdInTest

ndmitchell commented 5 years ago

Thanks for the report!

I suspect I don't have much choice. The code to hook up Ghcid to Ghci with pipes etc. is at https://github.com/ndmitchell/ghcid/blob/master/src/Language/Haskell/Ghcid.hs#L63-L69. Is the result of CreatePipe not seekable? If the test program leaves stdin in an inconsistent state, my guess is that it will severely upset Ghcid.

openingnow commented 4 years ago

Adding verbose option(ghcid --test=Main.main Main.hs -v) allows hDuplicate to work properly(prints content of test.txt). However even with verbose enabled, about 20% of triggering fails with same message(*** Exception: <stdin>: hDuplicate: illegal operation (cannot flush the read buffer: underlying device is not seekable))

I'm using macOS 10.15.5, GHC 8.8.3/8.10.1

ndmitchell commented 4 years ago

Surprised -v makes it work better, but I still think the underlying issue will remain - I hijack the stdin, and that means a test that tries to use stdin is going to have a hard time.