2012-01-23 13 views
12

通常の実行中のHaskell実行ファイルでcontrol-Cの中断効果を(一時的に)無効にする方法はありますか?control-Cを無効にすることはできますか?

コンテキスト:私は毎年少しずつ運動をしています。これは、hncursesを使用してシェルウィンドウで実行されている、パターンマッチングをトリガーする式の周りの学生のジッパーが適切に書き換えられるゲームです。生徒が最後のパズルを終えたら、彼らは私に送る必要がある個々のパスワードを得ます。 WindowsのベテランやUnix初心者で、もちろん(派手に)怠け者なので、パスワードを選択してcontrol-Cを入力する傾向があります。これには、プログラムの中断やパスワードの消失という意図しない影響があります。それを回復する唯一の方法は、運動を繰り返すことです。どのように残酷!

問題を回避する他の方法(警告メッセージの印刷やファイルへのパスワードの書き込みなど)がありますが、制御Cを無効にする方法があるのか​​どうか不思議です。

+0

これは数年前のことですが、シグナルブロックをインストールする代わりに、ユーザーの端末を再配線してIngoがあなたのプログラム内で提案したようなことをすることができるはずです。これは私を最もクリーンなアプローチとして捉えています。 – dfeuer

答えて

12

うん、あなただけの一時的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 

(。あなたはより直接的にそれを名前を付けたい場合にもsigINTとしてkeyboardSignalを書くことができます)

あなたはまた、Catch mIgnoreを置き換えることができますここで、mは、テキストの正しいコピー方法に関するガイダンスを出力するアクションです。 (ただし、注意してください、それは別のHaskellのスレッドで実行されます。)

1

はあなたが明示的に私はUserInterruptであると信じ例外、キャッチできます

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

迅速かつ簡単に、使用するシェル:

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

これには、プログラムが中断される可能性があるという利点があります。

関連する問題