2012-01-23 5 views
12

Есть ли способ отключить (временно) прерывающий эффект управления C в обычном исполняемом исполняемом файле Haskell?Могу ли я отключить управление-C?

Контекст: У меня есть небольшое упражнение, которое я устанавливаю каждый год. Это игра, в которой ученики застегивают на молнии вокруг выражений, запускающих сопоставление образцов, переписывая, как это применимо, и запускается в окне оболочки с помощью hncurses. Когда ученики закончили последнюю загадку, они получают индивидуальный пароль, который им нужно отправить мне. Будучи ветеранами 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 

Вы также могли бы заменить Ignore с Catch m , где 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 

Это дополнительное преимущество в том, что программы все еще могут быть прерваны.

Смежные вопросы