我可以禁用control-C吗?

时间:2012-01-23 09:51:39

标签: haskell io

有没有办法在常规的shell-Haskell可执行文件中禁用(临时)control-C的中断效果?

背景:我每年都会进行一些练习。这是一个游戏,学生拉链表达式触发模式匹配重写适用,使用hncurses在shell窗口中运行。当学生完成最后一个谜题后,他们会获得一个他们需要发送给我的个人密码。作为Windows老手和Unix新手,当然(非常)懒惰,他们倾向于选择密码并输入control-C。这会产生意外中断程序并导致密码消失的影响。恢复它的唯一方法是重复练习。多么残忍!

虽然还有其他方法可以解决问题(例如,打印警告消息或将密码写入文件),但我很想知道是否有办法禁用control-C。

3 个答案:

答案 0 :(得分: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

(如果您想直接命名,可以将keyboardSignal写为sigINT。)

您还可以将Ignore替换为Catch m,其中m是一些操作,可以打印有关正确复制文本的方法的指导。 (但要小心;它将在一个单独的Haskell线程中运行。)

答案 1 :(得分:8)

快速简便,使用shell:

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

这还有一个好处,即程序仍然可以中断。

答案 2 :(得分:1)

你可以明确地捕获异常,我认为是UserInterrupt

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