2012-01-23 75 views
12

有沒有辦法在正常運行中的Haskell可執行文件中禁用(暫時)control-C的中斷效果?我可以禁用control-C嗎?

背景:我有一個我每年設定的練習。這是一個遊戲,學生拉鍊表達式觸發模式匹配重寫,如果適用,使用hncurses在shell窗口中運行。當學生完成最後一個謎題時,他們會得到他們需要發送給我的個人密碼。作爲Windows退伍軍人和Unix新手,當然(虛擬)懶惰,他們傾向於選擇密碼並鍵入control-C。這具有中斷程序並導致其密碼消失的意想不到的效果。恢復它的唯一方法是重複這個練習。多殘忍!

雖然還有其他方法可以解決此問題(例如,打印警告消息或將密碼寫入文件),但我很想知道是否有辦法禁用控制-C。

+0

我知道這已經過時了幾年,但是您應該能夠按照Ingo在您的程序中所建議的做法重新佈線用戶的終端,而不是安裝信號塊。這使我成爲最乾淨的方法。 – dfeuer

回答

12

是的,你只需要暫時忽略SIGINT(你也可以寫keyboardSignal作爲sigINT,如果你想更直接地命名)

import Prelude hiding (catch) 
import Control.Exception 
import Control.Concurrent 
import System.Posix.Signals 

-- Ensures the original handler is restored even after an exception. 
-- 
-- installHandler returns the previous signal handler, so if you're 
-- tied to some existing main loop, you could instead just keep 
-- its return value around for later restoration. 
ignoreSignal :: Signal -> IO a -> IO a 
ignoreSignal sig = bracket (install Ignore) install . const 
    where install handler = installHandler sig handler Nothing 

pause :: IO() 
pause = threadDelay 2000000 

main :: IO() 
main = do 
    ignoreSignal keyboardSignal $ do 
    putStrLn "Ctrl+C disabled." 
    pause 
    putStrLn "\nCtrl+C re-enabled." 
    pause 

你也可以用Catch m取代Ignore ,其中m是在複製文本的正確方式上打印指導的一些操作。 (要小心,雖然,它會在一個單獨的Haskell線程來運行。)

1

你可以明確地捕捉到了異常,我相信這是UserInterrupt

handle (\exception -> do 
    case fromException exception of 
      Just UserInterrupt -> -- return to problem 
      _     -> error "unhandled exception") playWithStudents 
8

快速,方便,使用shell:

stty intr ^T 
run your haskell program here 
stty intr ^C 

這還有一個額外的好處,即程序仍然可以被中斷。

相關問題