Control thread to exit haskell application

不羁的心 提交于 2020-01-01 16:36:06

问题


I'm brand new to Haskell and in messing around with a few samples I've got a problem where I can't stop the program. I'm using Windows 7 and using runhaskell from ght. Ctrl-c doesn't work so I have to resort to the task manager which is a bit of a pain.

Instead of doing that how can I create a separate control thread that would wait until I typed q and then quit my Haskell application.

The application I've got the problem with is of the format:

main = do
 h <- connectTo server (PortNumber (fromInteger port))
 hSetBuffering h NoBuffering
 ... do some stuff with the socket handle ...
 listen h

listen :: Handle -> IO ()
listen h = forever $ do
  t <- hGetLine h
  let s = init t
  putStrLn s
where
  forever a = do a; forever a

In pseudo-code what I'd like to have is:

main = do
  waitForQuit
  ... original program ...

waitForQuit :: IO()
   option <- getChar
   if option == 'q' then
     ... kill the app ... 
   else 
     waitForQuit

回答1:


You should be able to do this with a Haskell thread, getChar and exit{With,Success,Failure}.

import Control.Concurrent
import System.Exit
import Data.Char (toLower)
import System.IO

main = do
    forkIO realMain
    exitOnQ

exitOnQ = do
    hSetBuffering stdin NoBuffering
    c <- getChar
    when (toLower c /= 'q') exitOnQ
    exitSuccess  -- or "exitWith" and some ExitCode value, use hoogle.

Breaking this down: You get concurrently via forkIO. Notice this isn't a separate OS thread, but a Haskell thread which is extremely lightweight. The exitOnQ thread needs to get keystrokes without delay - without the NoBuffering you'd have to hit q-[ENTER]. If the pressed key wasn't q (or Q) then we loop, otherwise we terminate the program via one of the many exit* calls.

WARNING: It is a very uncommon corner case, but GHC uses GC points as thread scheduling points (has this changed in the past two years?) so if your code is spending significant blocks of time performing lots of pure computations that have zero allocation then you can't use this method to quit (unless you have multiple OS threads via the threaded RTS and an +RTS -N# option).




回答2:


how can I create a separate control thread that would wait until I typed q and then quit my Haskell application.

You can create new threads with forkIO, which takes a chunk of code as an argument. E.g.

main = do
    forkIO waitForQuit
    ....

The quit handler will spend most of its time blocked on getChar, but when it wakes up, it can terminate the program, by throwing an exit exception, such as:

    exitWith ExitSuccess

You may need to compile the program with ghc -O -threaded to ensure the program main thread can make progress, while the handler is waiting on q



来源:https://stackoverflow.com/questions/5589799/control-thread-to-exit-haskell-application

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!