私は Haskell でスキーム インタープリター用の REPL を実装しています。UserInterrupt、StackOverflow、HeapOverflow などの非同期イベントを処理したいと考えています。基本的には、UserInterrupt が発生したときに現在の計算を停止して、 StackOverflow と HeapOverflow が発生したときの適切なメッセージなど。これを次のように実装しました。
repl evaluator = forever $ (do
putStr ">>> " >> hFlush stdout
out <- getLine >>= evaluator
if null out
then return ()
else putStrLn out)
`catch`
onUserInterrupt
onUserInterrupt UserInterrupt = putStrLn "\nUserInterruption"
onUserInterrupt e = throw e
main = do
interpreter <- getMyLispInterpreter
handle onAbort (repl $ interpreter "stdin")
putStrLn "Exiting..."
onAbort e = do
let x = show (e :: SomeException)
putStrLn $ "\nAborted: " ++ x
1 つの例外を除いて、期待どおりに動作します。インタープリターを起動して Ctrl-Z + Enter を押すと、次のようになります。
>>> ^Z
Aborted: <stdin>: hGetLine: end of file
Exiting...
そのとおりです。しかし、インタープリターを起動して Ctrl-C を押してから Ctrl-Z + Enter を押すと、次のようになります。
>>>
UserInterruption
>>> ^Z
そして、ハングして、インタープリターを使用できなくなりました。ただし、もう一度 Ctrl-C を押すと、REPL のブロックが解除されます。いろいろ調べたのですが、原因がわかりません。誰でも説明できますか?
どうもありがとう!