【问题标题】:Can I disable control-C?我可以禁用 control-C 吗?
【发布时间】:2012-01-23 09:51:38
【问题描述】:

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

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

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

【问题讨论】:

  • 我知道这已经过时了几年,但您应该能够在您的程序中执行 Ingo 建议的操作,重新连接用户终端而不是安装信号块。我觉得这是最干净的方法。

标签: haskell io


【解决方案1】:

是的,你只需要暂时忽略 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 线程中运行。)

【讨论】:

    【解决方案2】:

    快速简单,使用shell:

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

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

    【讨论】:

      【解决方案3】:

      您可以显式捕获异常,我认为是UserInterrupt

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

      【讨论】:

        猜你喜欢
        • 2011-04-26
        • 2014-05-21
        • 1970-01-01
        • 2018-07-27
        • 1970-01-01
        • 1970-01-01
        • 2014-01-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多