有没有办法在常规的shell-Haskell可执行文件中禁用(临时)control-C的中断效果?
背景:我每年都会进行一些练习。这是一个游戏,学生拉链表达式触发模式匹配重写适用,使用hncurses在shell窗口中运行。当学生完成最后一个谜题后,他们会获得一个他们需要发送给我的个人密码。作为Windows老手和Unix新手,当然(非常)懒惰,他们倾向于选择密码并输入control-C。这会产生意外中断程序并导致密码消失的影响。恢复它的唯一方法是重复练习。多么残忍!
虽然还有其他方法可以解决问题(例如,打印警告消息或将密码写入文件),但我很想知道是否有办法禁用control-C。
答案 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