New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Windows: unsafe FFI import of getch does not play well with Control.Concurrent #1

Closed
rcook opened this Issue Jul 20, 2017 · 2 comments

Comments

Projects
None yet
1 participant
@rcook
Owner

rcook commented Jul 20, 2017

Repro program:

{-# LANGUAGE ForeignFunctionInterface #-}

import Control.Concurrent

import qualified Foreign.C.Types as FT
import qualified Data.Char       as C

{- On linux I compile with: wine ghc -threaded --make richard.hs
              and run with: wine richard.exe

   With `unsafe` thread B is broken (you need to push chars to wake it up).

   With "safe", threadB gets back to normal, outputting a string
   every 1 second.

   I verified (through a friend) this behaviour on native Windows.
-}

main = forkOS threadA >>
       -- we need forkOS because ffi, remember to compile with -threaded
       threadB

-- Threads --

threadA, threadB :: IO ()
threadA = do c <- getCharWindows
             putStrLn $ "thread A character:" ++  [c]
             threadA

threadB = do putStrLn "thread B, bby!"
             threadDelay (1 * 10^6)
             threadB

-- Ancillaries --

getCharWindows :: IO Char
getCharWindows = fmap (C.chr . fromEnum) c_getch
foreign import ccall unsafe "conio.h getch"
  c_getch :: IO FT.CInt

Thanks to Francesco Ariis (here and here) for reporting this issue and providing the repro program.

@rcook

This comment has been minimized.

Show comment
Hide comment
@rcook

rcook Jul 20, 2017

Owner

Judging by this discussion, anything that blocks (which is certainly true of getch) should be imported as safe not unsafe.

Owner

rcook commented Jul 20, 2017

Judging by this discussion, anything that blocks (which is certainly true of getch) should be imported as safe not unsafe.

@rcook

This comment has been minimized.

Show comment
Hide comment
@rcook

rcook Jul 20, 2017

Owner

More evidence that importing as safe is the way to go:

https://www.reddit.com/r/haskell/comments/1vsw1z/how_to_work_around_blocking_in_an_unsafe_ffi_call/
http://blog.ezyang.com/2010/07/safety-first-ffi-and-threading/

There is the concern that safe imports slow down the function call significantly. However, I think that this is largely irrelevant for this kind of function since it's heavily I/O-bound and waiting on human input.

Owner

rcook commented Jul 20, 2017

More evidence that importing as safe is the way to go:

https://www.reddit.com/r/haskell/comments/1vsw1z/how_to_work_around_blocking_in_an_unsafe_ffi_call/
http://blog.ezyang.com/2010/07/safety-first-ffi-and-threading/

There is the concern that safe imports slow down the function call significantly. However, I think that this is largely irrelevant for this kind of function since it's heavily I/O-bound and waiting on human input.

@rcook rcook self-assigned this Jul 20, 2017

@rcook rcook added the bug label Jul 20, 2017

rcook added a commit that referenced this issue Jul 20, 2017

@rcook rcook closed this in a13361a Jul 20, 2017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment