Help us understand the problem. What is going on with this article?

HaskellでCtrl-Cを制御する

More than 1 year has passed since last update.

SIGINT等のシグナルの扱い方です。

tl;dr

System.Posix.Signalsを使います

2019/1/25 追記

WindowsでCtrl-Cを制御する方法については @kakkun61 氏の記事を参照してください
Haskell で Ctrl-C を制御する(Windows) - 趣味はデバッグ……


Ctrl-Cが押されたらクロージングの処理を伴って終了するプログラムを書いてみます。

import Control.Concurrent
import System.Posix.Signals

main :: IO ()
main = do
    tid <- myThreadId
    let handler = do
            putStrLn "goodbye!"
            killThread tid
    installHandler keyboardSignal (Catch handler) Nothing

    let loop n = do
            putStr $ show n ++ ", "
            threadDelay 1000000
            loop (n+1)
    loop 0

実行してみましょう

$ runhaskell Main.hs
0, 1, 2, 3, 4, 5, ^Cgoodbye!
Main.hs: thread killed
$

ちゃんとgoodbyeと出力されて終了しました!killThreadは例外を伴って終了するのでMain.hs: thread killedというメッセージが出てしまっています。もし気になるなら例外を握りつぶすかMVarを使って終了を監視する仕組みを作るといいでしょう。

肝心のSignalを制御する関数はinstallHandler :: Signal -> Handler -> Maybe SignalSet -> IO Handlerです。Signelには制御するSignal、HandlerにはSignalが投げられた時の処理、Maybe SignalSetには処理時にブロックする他のSignalを指定します。

Signalの値は予め用意されていて

Function Signal
keyboardSignal SIGINT
keyboardStop SIGTSTP
keyboardTermination SIGQUIT
openEndedPipe SIGPIPE

と言った感じです。

HandlerDefaultにすれば標準の動作を、Ignoreにすれば何もしなくなり、Catch (IO ())で処理を記述すればSignalが投げられた時の処理を記述することができます。上の例ではhandlerという関数にメッセージの表示とメインスレッドの停止の処理を書いてHandlerとして渡していました。

簡単に解説しましたがまだまだ色々な使い方ができるので是非一度System.Posix.Signalsを読んでみてください(^^)

lotz
実用関数型プログラミング言語 Haskell の情報を発信しています
http://lotz84.github.io/
folio-sec
誰もがかんたんに資産運用することができるサービス「フォリオ」を作っているFinTech系スタートアップ
https://corp.folio-sec.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away